Module:Sanctions and Module:Sanctions/sandbox: Difference between pages
Appearance
(Difference between pages)
Content deleted Content added
Change Tmbox type to 'content' to sync with contentious topics talk page notice |
No edit summary |
||
Line 1: | Line 1: | ||
local p = {} |
|||
local getArgs = require('Module:Arguments').getArgs |
local getArgs = require('Module:Arguments').getArgs |
||
local yesno = require('Module:Yesno') |
local yesno = require('Module:Yesno') |
||
local rawData = mw.loadData('Module:Sanctions/data/sandbox') |
|||
local rawData = mw.loadData('Module:Sanctions/data') |
|||
local data = rawData.sanctions |
local data = rawData.sanctions |
||
local |
local commData = rawData.comm |
||
local arbcomData = rawData.arbcom |
|||
local messageBox = require('Module:Message box') |
local messageBox = require('Module:Message box') |
||
Line 22: | Line 23: | ||
if data[topicAlias] then |
if data[topicAlias] then |
||
return data[topicAlias] |
return data[topicAlias] |
||
elseif aliasMap[topicAlias] then |
|||
return data[aliasMap[topicAlias]] |
|||
else |
else |
||
return false |
return false |
||
Line 30: | Line 29: | ||
-- Returns an invalid topic error, with a table of acceptable topics |
-- Returns an invalid topic error, with a table of acceptable topics |
||
local function syntaxHelp() |
local function syntaxHelp(frame) |
||
return |
return '<span class="error">{{para|topic}} not specified. Available options:</span><div style="border-left: 5px dashed black; border-right: 5px dashed black; border-bottom: 5px dashed black; padding-left: 0.5em; padding-right: 0.5em; padding-bottom: 0.5em;">' .. p.table(frame) .. '</div>' |
||
{{Gs/topics/table}} |
|||
</div>]] |
|||
end |
end |
||
Line 54: | Line 51: | ||
function Topic:exists() |
function Topic:exists() |
||
return |
return self._topicData and true |
||
end |
end |
||
Line 62: | Line 59: | ||
function Topic:hasLocalRestriction(type) |
function Topic:hasLocalRestriction(type) |
||
return yesno(self._args[type]) or false |
|||
if localRestriction then |
|||
if mw.ustring.find(type, '^restriction') ~= nil then |
|||
return true |
|||
else |
|||
return yesno(localRestriction) |
|||
end |
|||
else |
|||
return false |
|||
end |
|||
end |
end |
||
Line 89: | Line 77: | ||
function Topic:hasAnyRevertRestrictions() |
function Topic:hasAnyRevertRestrictions() |
||
return self:hasRestrictions({'1rr', 'consensusrequired', 'brd'}) |
return self:hasRestrictions({'1rr', '0rr', 'consensusrequired', 'brd', 'protection'}) |
||
end |
end |
||
function Topic:hasAnyRestrictions() |
function Topic:hasAnyRestrictions() |
||
return self:hasAnyRevertRestrictions() or self:hasRestrictions({'restriction1'}) |
return self:hasAnyRevertRestrictions() or self:hasRestrictions({'restriction1'}) |
||
end |
|||
function Topic:getType() |
|||
return (self:get('type') == 'arbcom' and '[[WP:ARBCOM|Arbitration Committee]]' or (self:get('type') == "both" and '[[WP:ARBCOM|Arbitration Committee]] and community' or 'community')) |
|||
end |
|||
function Topic:getTypeUnlinked() |
|||
return (self:get('type') == 'arbcom' and 'arbitration' or (self:get('type') == "both" and 'arbitration and community' or 'community')) |
|||
end |
end |
||
Line 105: | Line 101: | ||
table.insert(customRestrictions, checkArr['restriction'..ri]) |
table.insert(customRestrictions, checkArr['restriction'..ri]) |
||
ri = ri + 1 |
ri = ri + 1 |
||
elseif breakNext then |
|||
break |
|||
else |
else |
||
ri = 1 |
|||
checkArr = self._args |
|||
break |
|||
breakNext = true |
|||
else |
|||
ri = 1 |
|||
checkArr = self._args |
|||
breakNext = true |
|||
end |
|||
end |
end |
||
end |
end |
||
Line 121: | Line 115: | ||
-- End classes |
-- End classes |
||
local function formatRestrictions(topic, you, article) |
|||
local restrictionList = mw.html.create('ul') |
|||
if (you) then |
|||
if topic:hasRestriction('1rr') then |
|||
restrictionList:tag('li'):wikitext('You are not allowed to make more than 1 revert within 24 hours on a page within this topic, subject to the [[WP:NOT3RR|usual exemptions]].') |
|||
end |
|||
if topic:hasRestriction('0rr') then |
|||
restrictionList |
|||
:tag('li') |
|||
:wikitext("You are not allowed to make any reverts within this topic, subject to the [[WP:NOT3RR|usual exemptions]].") |
|||
end |
|||
if topic:hasRestriction('protection') then |
|||
local protectionRestriction = '' |
|||
local shortCode = topic:get('restrictions')['protection'] |
|||
if shortCode == "ecp" then |
|||
protectionRestriction = "logged in, have made 500 edits, and an account age of 30 days" |
|||
elseif shortCode == "semi" then |
|||
protectionRestriction = "logged in, have made 10 edits, and an account age of 4 days" |
|||
elseif shortCode == "user" then |
|||
protectionRestriction = "logged in" |
|||
end |
|||
restrictionList:tag('li'):wikitext('You must be ' .. protectionRestriction .. '.') |
|||
end |
|||
local customRestrictions = topic:getCustomRestrictions() |
|||
for _, v in ipairs(customRestrictions) do |
|||
restrictionList |
|||
:tag('li') |
|||
:wikitext(v) |
|||
end |
|||
else |
|||
-- 1RR |
|||
if topic:hasRestriction('1rr') then |
|||
restrictionList |
|||
:tag('li') |
|||
:wikitext("'''Limit of one revert in 24 hours:''' This " .. (article and " article " or " topic ") .. " is under [[Wikipedia:Edit warring#Other revert rules|WP:1RR]] (one [[Wikipedia:Reverting|revert]] per editor per article ''per 24-hour period'').") |
|||
end |
|||
-- 0RR |
|||
if topic:hasRestriction('0rr') then |
|||
restrictionList |
|||
:tag('li') |
|||
:wikitext("'''Reverts prohibited:''' This " .. (article and " article " or " topic ") .. " is under [[Wikipedia:Edit warring#Other revert rules|WP:0RR]] (no reverts permitted).") |
|||
end |
|||
if topic:hasRestriction('protection') then |
|||
local protectionRestriction = '' |
|||
local shortCode = topic:get('restrictions')['protection'] |
|||
if shortCode == "ecp" then |
|||
protectionRestriction = "'''Extended confirmed requirement:''' Editors must be logged in, [[WP:ECP|have made 500 edits, and an account age of 30 days]]" |
|||
elseif shortCode == "semi" then |
|||
protectionRestriction = "'''Auto confirmed requirement:''' Editors must be logged in, [[WP:SEMI|have made 10 edits, and an account age of 4 days]]" |
|||
elseif shortCode == "user" then |
|||
protectionRestriction = "'''Logged in requirement:''' Editors must be logged in" |
|||
end |
|||
restrictionList |
|||
:tag('li'):wikitext(protectionRestriction .. " in order to make edits " .. (article and " to this article" or " within this topic area") .. ".") |
|||
end |
|||
-- Text for boilerplate/predefined restrictions |
|||
if topic:hasRestriction('consensusrequired') then |
|||
restrictionList |
|||
:tag('li') |
|||
:wikitext("'''Consensus required:''' All editors must obtain [[WP:Consensus|consensus]] on the talk page of " .. (article and "this article" or "articles within this topic") .. " before reinstating ''any edits that have been challenged (via reversion).'' This includes making edits similar to the ones that have been challenged. If in doubt, do not make the edit.") |
|||
end |
|||
if topic:hasRestriction('brd') then |
|||
restrictionList |
|||
:tag('li') |
|||
:wikitext("'''24-hr [[Wikipedia:BOLD, revert, discuss cycle|BRD cycle]]:''' If a change you make to " .. (article and "this article" or "an article within this topic") .." is reverted, you may not reinstate that change unless you discuss the issue on the talk page and wait 24 hours (from the time of the original edit). Partial reverts/reinstatements that reasonably address objections of other editors [[Wikipedia:BOLD, revert, discuss cycle#WP:BRR|are preferable]] to wholesale reverts.") |
|||
end |
|||
local customRestrictions = topic:getCustomRestrictions() |
|||
for _, v in ipairs(customRestrictions) do |
|||
restrictionList |
|||
:tag('li') |
|||
:wikitext(v) |
|||
end |
|||
end |
|||
return restrictionList |
|||
end |
|||
-- This function builds a talk notice |
-- This function builds a talk notice |
||
-- TODO: split this up |
-- TODO: split this up |
||
Line 140: | Line 214: | ||
:tag('span') |
:tag('span') |
||
:css('font-size', '120%') |
:css('font-size', '120%') |
||
:wikitext("'''WARNING: ACTIVE |
:wikitext("'''WARNING: ACTIVE " .. string.upper(topic:getTypeUnlinked()) .. " SANCTIONS'''") |
||
end |
end |
||
Line 146: | Line 220: | ||
out |
out |
||
:tag('p') |
:tag('p') |
||
:wikitext("The article [[:{{SUBJECTPAGENAME}}]], along with other pages relating to "..topic:get('scope')..", is designated by the |
:wikitext("The article [[:{{SUBJECTPAGENAME}}]], along with other pages relating to "..topic:get('scope')..", is designated by the " .. topic:getType() .. " as a '''[[Wikipedia:Contentious topics|contentious topic]]'''. The current restrictions are:") |
||
else |
else |
||
out |
out |
||
:tag('p') |
:tag('p') |
||
:wikitext("<strong>The use of the [[Wikipedia:Contentious topics|contentious topics procedure]] has been |
:wikitext("<strong>The use of the [[Wikipedia:Contentious topics|contentious topics procedure]] has been authorized by the " .. topic:getType() .. " for pages related to ".. topic:get('scope') ..", including this page.</strong>" .. (type == 'mini' and ' Editors who repeatedly or seriously fail to adhere to the [[Wikipedia:Five pillars|purpose of Wikipedia]], any expected [[Wikipedia:Etiquette|standards of behaviour]], or any [[Wikipedia:List of policies|normal editorial process]] may be sanctioned.' or '')) |
||
end |
end |
||
if |
if type ~= 'mini' then |
||
local restrictionList = |
local restrictionList = formatRestrictions(topic, false, true) |
||
-- 1RR |
|||
if topic:hasRestriction('1rr') then |
|||
restrictionList |
|||
:tag('li') |
|||
:wikitext("'''Limit of one revert in 24 hours:''' This article is under [[Wikipedia:Edit warring#Other revert rules|WP:1RR]] (one [[Wikipedia:Reverting|revert]] per editor per article ''per 24-hour period'') [[Category:Wikipedia pages subject to a one-revert restriction]]") |
|||
end |
|||
-- Text for boilerplate/predefined restrictions |
|||
if topic:hasRestriction('consensusrequired') then |
|||
restrictionList |
|||
:tag('li') |
|||
:wikitext("'''Consensus required:''' All editors must obtain [[WP:Consensus|consensus]] on the talk page of this article before reinstating ''any edits that have been challenged (via reversion).'' This includes making edits similar to the ones that have been challenged. If in doubt, do not make the edit. [[Category:Wikipedia pages subject to a consensus required restriction]]") |
|||
end |
|||
if topic:hasRestriction('brd') then |
|||
restrictionList |
|||
:tag('li') |
|||
:wikitext("'''24-hr [[Wikipedia:BOLD, revert, discuss cycle|BRD cycle]]:''' If a change you make to this article is reverted, you may not reinstate that change unless you discuss the issue on the talk page and wait 24 hours (from the time of the original edit). Partial reverts/reinstatements that reasonably address objections of other editors [[Wikipedia:BOLD, revert, discuss cycle#WP:BRR|are preferable]] to wholesale reverts. [[Category:Wikipedia pages subject to an enforced BRD restriction]]") |
|||
end |
|||
local customRestrictions = topic:getCustomRestrictions() |
|||
for _, v in ipairs(customRestrictions) do |
|||
restrictionList |
|||
:tag('li') |
|||
:wikitext(v) |
|||
end |
|||
if hasRestrictions then |
if hasRestrictions then |
||
Line 189: | Line 236: | ||
out |
out |
||
:tag('p') |
:tag('p') |
||
:wikitext("Editors who repeatedly or seriously fail to adhere to the [[Wikipedia: |
:wikitext("Editors who repeatedly or seriously fail to adhere to the [[Wikipedia:Five pillars|purpose of Wikipedia]], any expected [[Wikipedia:Etiquette|standards of behaviour]], or any [[Wikipedia:List of policies|normal editorial process]] may be sanctioned.") |
||
-- Further info box |
-- Further info box |
||
Line 206: | Line 253: | ||
enforcementProcedures |
enforcementProcedures |
||
:tag('li') |
:tag('li') |
||
:wikitext("Violations of any restrictions " .. (hasRevertRestrictions and "(excluding 1RR/reverting violations) " or "") .. "and other conduct issues should be reported to the [[ |
:wikitext("Violations of any restrictions " .. (hasRevertRestrictions and "(excluding 1RR/reverting violations) " or "") .. "and other conduct issues should be reported to the " .. (topic:get('type') == "arbcom" and "[[WP:AE|arbitration enforcement noticeboard]]" or "[[WP:ANI|administrators' incidents noticeboard]]") .. "." .. (hasRevertRestrictions and " Violations of revert restrictions should be reported to the [[Wikipedia:Administrators' noticeboard/Edit warring|administrators' edit warring noticeboard]]." or "")) |
||
:done() |
:done() |
||
:tag('li') |
:tag('li') |
||
Line 214: | Line 261: | ||
enforcementProcedures |
enforcementProcedures |
||
:tag('li') |
:tag('li') |
||
:wikitext("Problems should be reported to the [[ |
:wikitext("Problems should be reported to the " .. (topic:get('type') == "arbcom" and "[[WP:AE|arbitration enforcement noticeboard]]" or "[[WP:ANI|administrators' incidents noticeboard]]") .. ".") |
||
:done() |
:done() |
||
end |
end |
||
Line 243: | Line 290: | ||
:allDone() |
:allDone() |
||
:tag('p') |
:tag('p') |
||
:wikitext("If you are unsure if your edit is appropriate, discuss it here on this talk page first. <strong>Remember: When in doubt, don't revert!</strong>") |
|||
end |
end |
||
Line 260: | Line 307: | ||
local box = messageBox.main( 'tmbox', { |
local box = messageBox.main( 'tmbox', { |
||
type = ' |
type = 'notice', |
||
image = type == 'long' and '[[File:Commons-emblem-issue.svg|50px]]' or '[[File:Commons-emblem-hand-orange.svg|40px]]', |
image = type == 'long' and '[[File:Commons-emblem-issue.svg|50px]]' or '[[File:Commons-emblem-hand-orange.svg|40px]]', |
||
text = frame:preprocess(tostring(out)) |
text = frame:preprocess(tostring(out)) |
||
Line 268: | Line 315: | ||
end |
end |
||
-- Builds an alert notice |
-- Builds an intro alert notice |
||
-- |
-- |
||
-- @param frame |
-- @param frame |
||
-- @param topic topic class instance |
-- @param topic topic class instance |
||
-- @returns String representation of notice |
-- @returns String representation of notice |
||
local function |
local function buildFirstAlert(frame, topic, sig) |
||
local out = mw.html.create('table') |
local out = mw.html.create('table') |
||
:addClass('gs-alert') |
:addClass('gs-alert') |
||
:cssText("border: 1px solid #AAA; background-color: #E5F8FF; padding: 0.5em; width: 100%; margin-bottom: 1em") |
:cssText("border: 1px solid #AAA; background-color: #E5F8FF; padding: 0.5em; width: 100%; margin-bottom: 1em") |
||
local insideNode = out |
|||
out |
|||
:tag('tr') |
:tag('tr') |
||
:tag('td') |
:tag('td') |
||
Line 285: | Line 332: | ||
:done() |
:done() |
||
:tag('td') |
:tag('td') |
||
:wikitext("This is a standard message to notify contributors about an administrative ruling in effect. ''It does '''not''' imply that there are any issues with your contributions to date.''") |
|||
insideNode |
|||
:newline() |
|||
:tag('p'):wikitext("You have recently edited a page related to <b>" .. topic:get('scope') .. "</b>, a topic designated as [[WP:CTOP|contentious]] by the " .. topic:getType() .. "."):done() |
|||
:wikitext("You have shown interest in ".. topic:get('scope') ..". Due to past disruption in this topic area, the community has authorised uninvolved administrators to impose [[Wikipedia:Contentious topics|contentious topics restrictions]]—such as [[Wikipedia:Editing restrictions#Types of restrictions|editing restrictions]], [[Wikipedia:Banning policy#Types of bans|bans]], or [[WP:Blocking policy|blocks]]—on editors who do not strictly follow [[Wikipedia:List of policies|Wikipedia's policies]], expected [[Wikipedia:Etiquette|standards of behaviour]], or the [[Wikipedia:Contentious topics#Standard set|page-specific restrictions]], when making edits related to the topic.") |
|||
:tag('p'):wikitext("A special set of rules applies to certain topic areas, which are referred to as <i>contentious topics</i>. These are specially designated topics that have been identified by the community or the Arbitration Committee to attract more persistent disruptive editing than the rest of the project. When editing a contentious topic, Wikipedia’s norms and policies are more strictly enforced, and Wikipedia administrators have special powers in order to reduce disruption to the project."):done() |
|||
:newline() |
|||
:tag('p'):wikitext("Within contentious topics, editors should edit <strong>carefully</strong> and <strong>constructively</strong>, refrain from disrupting the encyclopedia, and:"):done() |
|||
:wikitext("For additional information, please see the [[".. topic:get('wikilink') .."|guidance on these sanctions]]. If you have any questions, or any doubts regarding what edits are appropriate, you are welcome to discuss them with me or any other editor." .. (sig and ' '..sig or '')) |
|||
:tag('ul') |
|||
:tag('li'):wikitext('adhere to the [[WP:NOT|purposes of Wikipedia]];'):done() |
|||
:tag('li'):wikitext('comply with all applicable [[Wikipedia:Policies and guidelines|policies and guidelines]];'):done() |
|||
:tag('li'):wikitext('follow editorial and behavioural best practice;'):done() |
|||
:tag('li'):wikitext('comply with any page restrictions in force within the area of conflict; and'):done() |
|||
:tag('li'):wikitext('refrain from [[WP:GAME|gaming the system]].'):done() |
|||
:done() |
|||
if (topic:hasAnyRestrictions()) then |
|||
insideNode |
|||
:tag('p'):wikitext("Additionally, you must comply with the following restrictions:") |
|||
local restrictionList = formatRestrictions(topic, true, false) |
|||
insideNode:wikitext(tostring(restrictionList)):done() |
|||
end |
|||
insideNode |
|||
:tag('p'):wikitext("Editors are advised to err on the side of caution if unsure whether making a particular edit is consistent with these expectations. If you have any questions about contentious topics ''procedures'' you may ask them at the [[WT:AC/C|arbitration clerks' noticeboard]] or you may learn more about this contentious topic at [[" .. topic:get('wikilink') .. "]]. You may also choose to note which contentious topics you know about by using the {{tl|ct/aware}} template."):done() |
|||
return frame:preprocess('== Introduction to contentious topics ==\n' .. tostring(out) .. ' <!-- Derived from Template:Contentious topics/alert --> ') |
|||
end |
|||
-- Builds an alert notice |
|||
return frame:preprocess(tostring(out)) |
|||
-- |
|||
-- @param frame |
|||
-- @param topic topic class instance |
|||
-- @returns String representation of notice |
|||
local function buildAlert(frame, topic, sig) |
|||
local out = '' |
|||
out = out .. '[[File:Commons-emblem-notice.svg|link=|25px|alt=Information icon]] You have recently made edits related to ' .. topic:get('scope') .. '. This is a standard message to inform you that ' .. topic:get('scope') .. ' is a' .. (topic:get('type') == "comm" and ' community' or 'n Arbitration Committee' .. (topic:get('type') == "both" and ' and community' or '')) .. ' designated contentious topic. This message <em>does <strong>not</strong> imply that there are any issues with your editing</em>. ' |
|||
if (topic:hasAnyRestrictions()) then |
|||
out = out .. "You must comply with the following restrictions within this topic area:" |
|||
local restrictionList = formatRestrictions(topic, true, false) |
|||
out = out .. tostring(restrictionList) .. '\n\n' |
|||
end |
|||
out = out .. 'For more information about the contentious topics system, please see [[Wikipedia:Contentious topics]].' |
|||
return frame:preprocess(tostring(out) .. ' <!-- Derived from Template:Contentious topics/alert --> ') |
|||
end |
end |
||
-- Builds an edit notice |
-- Builds an edit notice |
||
local function buildEditNotice(frame, topic, args) |
local function buildEditNotice(frame, topic, args) |
||
local enHeader = 'This page relates to '.. topic:get('scope') .. ', which has been designated by the ' .. topic:getType() .. ' as a [[WP:CTOP|contentious topic]].' |
|||
local enHeader = mw.html.create('') |
|||
local |
local enText = mw.html.create('') |
||
enText:tag('p'):wikitext('While editing this topic, you must adhere to the [[WP:Five pillars|purpose of Wikipedia]], [[WP:Etiquette|expected standards of behaviour]], and [[WP:List of policies|Wikipedia\'s policies and norms]].'):done() |
|||
local expiry = args['expiry'] or 'indefinite' |
|||
if topic:hasAnyRestrictions() then |
|||
local redirect = args['redirect'] or '' |
|||
local list = formatRestrictions(topic, true, true) |
|||
enText:tag('p'):wikitext("In addition, while editing, you must follow these restrictions: "):done() |
|||
if topic:hasRestriction('1rr') then |
|||
enText:wikitext(tostring(list)) |
|||
table.insert(restrictionMsgs, "Editors must not make more than one [[Help:Reverting|revert]] per 24 hours (subject to [[Wikipedia:Edit warring#Exemptions|exceptions]])") |
|||
end |
|||
if topic:hasRestriction('consensusrequired') then |
|||
table.insert(restrictionMsgs, "Editors must not reinstate any challenged edits (via reversion) without first obtaining [[Wikipedia:Consensus|consensus]] on the talk page of this article") |
|||
end |
end |
||
local customRestrictions = topic:getCustomRestrictions() |
|||
for _, v in ipairs(customRestrictions) do |
|||
table.insert(restrictionMsgs, v) |
|||
end |
|||
if #restrictionMsgs == 0 then |
|||
return frame:preprocess(syntaxHelp()) |
|||
else |
|||
local list = mw.html.create('ul') |
|||
for _,v in ipairs(restrictionMsgs) do |
|||
list |
|||
:tag('li') |
|||
:wikitext(v) |
|||
:done() |
|||
end |
|||
enHeader:wikitext(tostring(list)) |
|||
end |
|||
local enText = mw.html.create('') |
|||
enText |
enText |
||
:tag('p') |
:tag('p') |
||
:wikitext("<strong>Failure to do so may result in a block or other sanctions.</strong> Please edit carefully.") |
|||
:wikitext("<strong>Breaching the restriction on this page may result in a block or other sanctions.</strong> In addition, please note that because this topic area has been disrupted in the past, the community has [["..topic:get('wikilink').."|authorised]] administrators to take [[Wikipedia:Contentious topics|appropriate steps]] to ensure the smooth running of all pages related to "..topic:get('scope')..". Conduct which does not adhere to our policies and [[Wikipedia:Etiquette|standards of behaviour]] may be met with sanctions. Please edit carefully.") |
|||
:done() |
:done() |
||
local editnotice = frame:expandTemplate{ title = 'editnotice', args = { |
local editnotice = frame:expandTemplate{ title = 'editnotice', args = { |
||
expiry = |
expiry = "indefinite", |
||
headerstyle = "font-size: 120%;", |
headerstyle = "font-size: 120%;", |
||
style = "background: ivory;", |
style = "background: ivory;", |
||
image = "Commons-emblem-issue.svg", |
image = "Commons-emblem-issue.svg", |
||
imagesize = "50px", |
imagesize = "50px", |
||
redirect = tostring(redirect), |
|||
header = tostring(enHeader), |
header = tostring(enHeader), |
||
text = tostring(enText) |
text = tostring(enText) |
||
Line 345: | Line 399: | ||
return editnotice |
return editnotice |
||
end |
|||
local function buildAwarenessNotice(frame, topics, args) |
|||
local out = 'This user is aware of the designation of the following topics as [[WP:CTOP|contentious topics]]:\n' |
|||
for k,v in pairs(topics) do |
|||
out = out .. '* ' .. v:get('scope') .. '\n' |
|||
end |
|||
out = out .. "They '''should ''not'' be given alerts''' for those areas." |
|||
return messageBox.main( 'mbox', { |
|||
type = 'notice', |
|||
image = '[[File:Commons-emblem-notice.svg|40px]]', |
|||
text = frame:preprocess(out) |
|||
}) |
|||
end |
|||
-- Builds a sanction alert notice |
|||
-- |
|||
-- @param frame |
|||
-- @param topic topic class instance |
|||
-- @returns String representation of notice |
|||
local function buildSanctionAlert(frame, type, topic, sanction, rationale, decision, sig) |
|||
local out = mw.html.create('table') |
|||
:addClass('gs-alert') |
|||
:cssText("margin-bottom: 1em; border: 1px solid #AAA; background-color: ivory; padding: 0.5em; display: flex; align-items: center;") |
|||
local insideNode = out |
|||
:tag('tr') |
|||
:tag('td') |
|||
:cssText("vertical-align:middle; padding-left:1px; padding-right:0.5em;") |
|||
:wikitext("[[File:Commons-emblem-hand.svg|50px]]") |
|||
:done() |
|||
:tag('td') |
|||
insideNode |
|||
:tag('p'):wikitext("The following sanction has been applied to you: "):done() |
|||
:wikitext(frame:expandTemplate{title = "talkquote", args = {["1"] = (((sanction == "ban" and topic ~= nil) and "You have been banned from making edits related to " .. topic:get('scope') .. ", broadly construed." or sanction) or "<span class=\"error\">no sanction given</span>")}}) |
|||
:tag('p'):wikitext("You have been sanctioned " .. (rationale or "<span class=\"error\">no reason given</span>")):done() |
|||
:tag('p'):wikitext("This sanction is imposed in my capacity as an [[WP:UNINVOLVED|uninvolved administrator]] under the authority of " .. (type == "comm" and "the community" or "the [[WP:ARBCOM|arbitration committee]]" .. (type == "both" and " and the community" or "")) .. " at " .. (topic ~= nil and "[[" .. topic:get("wikilink") .. "]]" or (decision or "<span class=\"error\">no decision link provided</span>")) .. (topic ~= nil and ", and the [[WP:CTOP|contentious topics procedure]]." or ".") .. " This sanction has been recorded in the log of sanctions for that topic. If the sanction includes a ban, please read the [[Wikipedia:Banning policy|banning policy]] to ensure you understand what this means. If you do not comply with this sanction, you may be [[Wikipedia:Blocking policy|blocked]] for an extended period, by way of enforcement of this sanction—and you may also be made subject to further sanctions."):done() |
|||
:tag('p'):wikitext("You may appeal this sanction by " .. (topic ~= nil and "[[Wikipedia:Contentious topics#Appeals and Amendments|following the instructions here]]" or "[[WP:UNBAN|following the instructions here]]") .. ". Even if you appeal this sanction, you remain bound by it until you are notified by an uninvolved administrator that the appeal has been successful. You are also free to contact me on my talk page if anything of the above is unclear to you."):done() |
|||
return frame:preprocess('== You have been sanctioned ==\n' .. tostring(out) .. '\n <!-- Template:Ct/sanction -->') |
|||
end |
|||
local function listToText(frame, t) |
|||
local new = {} |
|||
local t = require('Module:TableTools').compressSparseArray(t) |
|||
for i,v in ipairs(t) do |
|||
table.insert(new, frame:expandTemplate{title = 'Contentious_topics/list', args = {["scope"] = v}}) |
|||
end |
|||
return '\n*'..table.concat(new, '\n*') |
|||
end |
end |
||
Line 350: | Line 453: | ||
-- EXPORTS |
-- EXPORTS |
||
--/////////-- |
--/////////-- |
||
local p = {} |
|||
function p.detect(frame) |
|||
local title |
|||
local args = getArgs(frame) |
|||
if args.testTitle then |
|||
title = mw.title.new(args.testTitle) |
|||
else |
|||
title = mw.title.getCurrentTitle() |
|||
end |
|||
local content = title:getContent() or '' |
|||
local codes = string.match(content, "{{%s-[cC]ontentious [tT]opics/[aA]ware%s-|([^}]-)}}") |
|||
local shortcutCodes = string.match(content, "{{%s-[cC][tT]/[aA]ware%s-|([^}]-)}}") |
|||
local dsCodes = string.match(content, "{{%s-D[sS]/[aA]ware%s-|([^}]-)}}") |
|||
if (not codes) and (not dsCodes) and (not shortcutCodes) then return end |
|||
local text |
|||
if ( codes ) then |
|||
text = listToText(frame, mw.text.split(codes, "|")) |
|||
elseif ( dsCodes ) then |
|||
text = listToText(frame, mw.text.split(dsCodes, "|")) |
|||
else |
|||
text = listToText(frame, mw.text.split(shortcutCodes, "|")) |
|||
end |
|||
return frame:preprocess( |
|||
"<div style = 'font-weight: bold'>It is not necessary to notify this user about the following topics being contentious topics:" |
|||
..text.. |
|||
"\n The user has indicated that they are already aware using the template <nowiki>{{Contentious topics/aware}}</nowiki> on their talk page.</div>" |
|||
) |
|||
end |
|||
-- Returns awareness notice |
|||
function p.awarenessNotice(frame) |
|||
local args = getArgs(frame) |
|||
local topics = {} |
|||
for k,v in ipairs(args) do |
|||
topics[k] = Topic.new(v, args) |
|||
if not topics[k]:exists() then |
|||
return frame:preprocess('<strong class="error">Invalid topic specified at argument ' .. k .. '</strong>. \n' .. p.table(frame)) |
|||
end |
|||
end |
|||
return buildAwarenessNotice(frame, topics, args) |
|||
end |
|||
-- Returns a talk notice |
-- Returns a talk notice |
||
-- For documentation, see [[Template:Gs/talk notice]] |
-- For documentation, see [[Template:Gs/talk notice]] |
||
function p.talknotice(frame) |
function p.talknotice(frame) |
||
local args = getArgs(frame |
local args = getArgs(frame) |
||
wrappers = { |
|||
'Template:Gs/talk notice', |
|||
'Template:Gs/talk notice/sandbox' |
|||
} |
|||
}) |
|||
local topic = Topic.new(args['topic'] or args[1], args) |
local topic = Topic.new(args['topic'] or args[1], args) |
||
if not topic:exists() then |
if not topic:exists() then |
||
return frame:preprocess(syntaxHelp()) |
return frame:preprocess(syntaxHelp(frame)) |
||
end |
end |
||
Line 374: | Line 514: | ||
-- For documentation, see [[Template:Gs/alert]] |
-- For documentation, see [[Template:Gs/alert]] |
||
function p.alert(frame) |
function p.alert(frame) |
||
local args = getArgs(frame |
local args = getArgs(frame) |
||
wrappers = { |
|||
'Template:Gs/alert', |
|||
'Template:Gs/alert/sandbox', |
|||
} |
|||
}) |
|||
local topic = Topic.new(args['topic'] or args[1], args) |
local topic = Topic.new(args['topic'] or args[1], args) |
||
if not topic:exists() then |
if not topic:exists() then |
||
return frame:preprocess(syntaxHelp()) |
return frame:preprocess(syntaxHelp(frame)) |
||
elseif not topic:hasRestriction('ds') then |
elseif not topic:hasRestriction('ds') then |
||
return frame:preprocess('<span class="error">This topic area is not designated as a contentious topic. Alert is not required.</span>') |
return frame:preprocess('<span class="error">This topic area is not designated as a contentious topic. Alert is not required.</span>') |
||
Line 389: | Line 524: | ||
return buildAlert(frame, topic, args['sig']) |
return buildAlert(frame, topic, args['sig']) |
||
end |
|||
function p.alertFirst(frame) |
|||
local args = getArgs(frame) |
|||
local topic = Topic.new(args['topic'] or args[1], args) |
|||
if not topic:exists() then |
|||
return frame:preprocess(syntaxHelp(frame)) |
|||
elseif not topic:hasRestriction('ds') then |
|||
return frame:preprocess('<span class="error">This topic area is not designated as a contentious topic. Alert is not required.</span>') |
|||
end |
|||
return buildFirstAlert(frame, topic, args['sig']) |
|||
end |
|||
function p.sanction(frame) |
|||
local args = getArgs(frame) |
|||
local topic = Topic.new(args['topic'] or args[1], args) |
|||
return buildSanctionAlert(frame, (topic:exists() and topic:get('type') or args['type']), (topic:exists() and topic or nil), args['sanction'], args['rationale'], args['decision'], args['sig']) |
|||
end |
end |
||
Line 394: | Line 549: | ||
-- For documentation, see [[Template:Gs/editnotice]] |
-- For documentation, see [[Template:Gs/editnotice]] |
||
function p.editnotice(frame) |
function p.editnotice(frame) |
||
local args = getArgs(frame |
local args = getArgs(frame) |
||
wrappers = { |
|||
'Template:Gs/editnotice', |
|||
'Template:Gs/editnotice/sandbox' |
|||
} |
|||
}) |
|||
local topic = Topic.new(args['topic'] or args[1], args) |
local topic = Topic.new(args['topic'] or args[1], args) |
||
if not topic:exists() then |
if not topic:exists() then |
||
return frame:preprocess(syntaxHelp()) |
return frame:preprocess(syntaxHelp(frame)) |
||
elseif not topic:hasAnyRestrictions() then |
|||
return frame:preprocess('<span class="error">Page sanctions are not authorised for this topic area. Edit notice is not required.</span>[[Category:Pages with sanctions errors]]') |
|||
end |
end |
||
Line 411: | Line 559: | ||
end |
end |
||
function p. |
function p.generatePage(frame) |
||
local args = getArgs(frame |
local args = getArgs(frame) |
||
local topic = Topic.new(args['topic'], args) |
|||
wrappers = { |
|||
local out = mw.html.create('') |
|||
'Template:Gs/topics/table', |
|||
out:wikitext(messageBox.main( 'ombox', { |
|||
'Template:Gs/topics/table/sandbox', |
|||
type = 'notice', |
|||
} |
|||
image = '[[File:Unbalanced scales.svg|50x40px|link=]]', |
|||
}) |
|||
text = 'This page documents and supplements decisions concerning a [[WP:CTOP|contentious topic]].' |
|||
})):done() |
|||
if (yesno(args['rescinded']) or false) then |
|||
out:tag('p'):wikitext('This topic previously had enacted remedies that applied to all editors who made edits to this topic area ("the Contentious Topic"). They have since been removed as a contentious topic.'):allDone() |
|||
return tostring(out) |
|||
else |
|||
if not topic:exists() then error("Topic does not exist, use rescinded parameter for former contentious topics") end |
|||
out:tag('p'):wikitext('The ' .. topic:getType() .. ' has [[' .. topic:get("decision") .. '|enacted remedies]] that apply to all editors who make edits related to <b>' .. topic:get("scope") .. '</b> ("the Contentious Topic"). The [[WP:CTOP|contentious topic procedure]] applies to all pages and edits related to this topic.' ):done() |
|||
end |
|||
out:tag('h2'):wikitext("Decisions"):done() |
|||
out:wikitext((args['decisions'] or '')):done() |
|||
out:tag('h2'):wikitext("Guidance for administrators"):allDone() |
|||
out:wikitext((args['guidance'] or '')):done() |
|||
out:tag('h2'):wikitext("Standard set of restrictions"):allDone() |
|||
out:tag("p"):wikitext("Any uninvolved administrator may impose the following set of restrictions for up to one year: "):allDone() |
|||
out:tag('ul') |
|||
:tag("li"):wikitext("Individual restrictions") |
|||
:tag("ul") |
|||
:tag("li"):wikitext("sitewide and partial blocks"):done() |
|||
:tag("li"):wikitext("topic bans and page bans (from the entire contentious topic, a subtopic, or specified pages within the topic),"):done() |
|||
:tag("li"):wikitext("interaction bans,"):done() |
|||
:tag("li"):wikitext("revert restrictions"):done() |
|||
:done() |
|||
:done() |
|||
:tag("li"):wikitext("Page restrictions") |
|||
:tag("ul") |
|||
:tag("li"):wikitext("page protection,"):done() |
|||
:tag("li"):wikitext("revert restrictions,"):done() |
|||
:tag("li"):wikitext('the "[[Wikipedia:Contentious topics#cite note-3|consensus required]]" restriction,'):done() |
|||
:tag("li"):wikitext('the "[[Wikipedia:Contentious topics#cite note-4|enforced BRD]]" restriction'):done() |
|||
:done() |
|||
:done() |
|||
:allDone() |
|||
local restrictionList = formatRestrictions(topic, false, false) |
|||
local hasRestrictions = topic:hasAnyRestrictions() |
|||
local hasRevertRestrictions = topic:hasAnyRevertRestrictions() |
|||
if hasRestrictions then |
|||
out:tag("p"):wikitext("The following restrictions apply to the whole topic area: "):done() |
|||
out:node(restrictionList) |
|||
end |
|||
out:tag('h2'):wikitext("Templates"):allDone() |
|||
out:tag("p"):wikitext("When alerting an editor who has never received an alert for any contentious topic, the following template <b>must</b> be used to alert them: " .. frame:preprocess("{{tlx|Contentious topics/alert/first|" .. args['topic'] .. "}}" )):done() |
|||
out:tag("p"):wikitext("In addition, the following <b>must</b> be used as an editnotice: " .. frame:preprocess("{{tlx|Contentious topics/editnotice|" .. args['topic'] .. "}}" )):done() |
|||
out:tag("p"):wikitext("And the following <b>must</b> be used as a talk notice: " .. frame:preprocess("{{tlx|Contentious topics/talk notice|" .. args['topic'] .. "}}" )):done() |
|||
return tostring(out) |
|||
end |
|||
function p.table(frame) |
|||
local args = getArgs(frame) |
|||
local type = args['type'] |
|||
local tbl = mw.html.create('table') |
local tbl = mw.html.create('table') |
||
:addClass('wikitable') |
:addClass('wikitable'):addClass('sortable') |
||
:css('font-size', '9pt') |
:css('font-size', '9pt') |
||
:css('background', 'transparent') |
:css('background', 'transparent') |
||
:css('color', 'inherit') |
:css('color', 'inherit') |
||
if (type ~= "comm" and type ~= "arbcom" and type ~= nil) then |
|||
return '<span class="error">Invalid sanction type specified.</span>' |
|||
end |
|||
local topRow = tbl:tag('tr') |
|||
-- Headers |
-- Headers |
||
topRow:tag('th') |
|||
:wikitext("Topic code") |
|||
:tag('th') |
|||
:done() |
|||
:wikitext("Topic code") |
|||
topRow:tag('th') |
|||
:wikitext("Area of conflict") |
|||
:done() |
|||
if (type ~= "comm" and type ~= "arbcom") then |
|||
topRow:tag('th') |
|||
:wikitext("Designated by") |
|||
:done() |
:done() |
||
end |
|||
:tag('th') |
|||
topRow:tag('th') |
|||
:wikitext("Area of conflict") |
|||
:wikitext("Relevant information") |
|||
:done() |
|||
: |
:done() |
||
topRow:tag('th') |
|||
:wikitext("Decision linked to") |
|||
:wikitext("Relevant decision") |
|||
:allDone() |
|||
:allDone() |
|||
-- sort alphabetically |
-- sort alphabetically |
||
local sortedTable = {} |
local sortedTable = {} |
||
if type == "comm" then |
|||
for n in pairs(data) do |
|||
for n in pairs(commData) do |
|||
table.insert(sortedTable, n) |
|||
table.insert(sortedTable, n) |
|||
end |
|||
elseif type == "arbcom" then |
|||
for n in pairs(arbcomData) do |
|||
table.insert(sortedTable, n) |
|||
end |
|||
else |
|||
for n in pairs(data) do |
|||
table.insert(sortedTable, n) |
|||
end |
|||
end |
end |
||
table.sort(sortedTable) |
table.sort(sortedTable) |
||
local added = {} |
|||
for _,v in ipairs(sortedTable) do |
for _,v in ipairs(sortedTable) do |
||
local sanction = data[v] |
local sanction = data[v] |
||
local wt = (function(sanction, v) |
|||
local title = mw.title.new(sanction.wikilink).redirectTarget -- probably unnecessarily expensive; just add to config |
|||
for l,w in ipairs(sanction.aliases or {}) do |
|||
tbl:tag('tr') |
|||
if (w == v) then return nil end |
|||
:tag('td') |
|||
end |
|||
:wikitext(frame:preprocess("{{tlx"..(args['subst'] and "s" or "").."|{{#ifeq:{{BASEPAGENAME}}|Gs|{{PAGENAME}}|{{BASEPAGENAME}}}}|<nowiki>topic=</nowiki><b>"..(sanction.palias or v).."</b>}}")) |
|||
local out = "<code>" .. v .. "</code>" |
|||
:done() |
|||
for l,w in ipairs(sanction.aliases or {}) do |
|||
:tag('td') |
|||
if (not added[w]) then |
|||
:wikitext(sanction.scope) |
|||
out = out .. ' ' .. "<code>" .. w .. "</code>" |
|||
:done() |
|||
added[w] = true |
|||
:tag('td') |
|||
end |
|||
:wikitext("[["..title.fullText.."]]") |
|||
end |
|||
return out |
|||
end)(sanction, v) |
|||
if wt ~= nil then |
|||
if (not added[v]) then |
|||
tbl:tag('tr') |
|||
:tag('td') |
|||
:wikitext(wt) |
|||
:done() |
|||
:tag('td') |
|||
:wikitext(sanction.scope) |
|||
:done() |
|||
:tag('td') |
|||
:wikitext(sanction.type == "comm" and "the community" or "the Arbitration Committee" .. (sanction.type == "both" and " and the community" or "")) |
|||
:done() |
|||
:tag('td') |
|||
:wikitext("[[".. sanction.wikilink .."]]") |
|||
:done() |
|||
:tag('td') |
|||
:wikitext((sanction.decision ~= nil and "[[".. sanction.decision .. "|decision]]" or "")) |
|||
:allDone() |
|||
added[v] = true |
|||
end |
|||
end |
|||
end |
end |
||
Line 463: | Line 706: | ||
function p.topicsHelper(frame) |
function p.topicsHelper(frame) |
||
local args = getArgs(frame |
local args = getArgs(frame) |
||
wrappers = { |
|||
'Template:Gs/topics', |
|||
'Template:Gs/topics/sandbox' |
|||
} |
|||
}) |
|||
if args['sanctions scope'] and data[args['sanctions scope']] then |
if args['sanctions scope'] and data[args['sanctions scope']] then |
||
Line 482: | Line 720: | ||
function p.checkIfValidTopic(topicName) |
function p.checkIfValidTopic(topicName) |
||
local topic = Topic.new(topicName, nil) |
local topic = Topic.new(topicName, nil) |
||
return topic:exists() |
|||
return true |
|||
else |
|||
return false |
|||
end |
|||
end |
end |
||
-- for debugging |
|||
p._Topic = Topic |
|||
return p |
return p |