-- For attribution: [[:vi:Module:CurrentCandidateList]]
local p = {}
local perm = {'GRN', 'GP', 'GS', 'GR'}
local title = 'Steward requests/Global permissions' -- Here's our title...
local content = mw.title.new(title):getContent() -- ...and here's our content.
function p.list(frame) -- {{#invoke:Votings-global|list}} will output a pipe-separated list of numbers of requests.
local list = { -- Data.
GR = {
pat = 'roll%s*backe?r?',
num = 0,
boo = false
},
GS = {
pat = 'sysop',
num = 0,
boo = false
},
GRN = {
pat = 'renamer?',
num = 0,
boo = false
},
GP = {
num = 0
}
}
local b = { -- Originally "b" means "boolean". Now it's a table that contains boolean values.
a = false,
b = false,
c = {}
}
-- These statuses mark the requests as no longer active.
local s = {'done', '+', 'cannot', 'notdone', '-', 'alreadydone', 'withdrawn', 'redundant'}
for k, v in pairs(list) do -- Iterate the "list" table.
if k ~= 'GP' then -- "GP" stands for "Other global permissions". The old template used it; I don't know why.
for l in mw.text.gsplit(content, '\n') do -- Iterate lines of SRGP
if p.catch(l, list, k) then -- See p.catch (case 1), then come back here.
list[k].boo = true -- We're going through GR/GS/GRN h3 section(s).
end
if list[k].boo and mw.ustring.match(l, '%s*%|%s*status%s*=%s*.*') and not p.inc(p.status(l), s) then -- See p.inc and p.status.
list[k].num = list[k].num + 1 -- If the line contains status param and its value is not one of "s", add one to total.
list[k].boo = false -- One subsection can only contain one request.
elseif mw.ustring.match(l, '===%s*.+%s*===') and not p.catch(l, list, k) then -- No longer in that subsection.
list[k].boo = false -- Nothing caught, nothing added.
end
end
else
for l in mw.text.gsplit(content, '\n') do -- Iterate lines of SRGP, again.
if mw.ustring.match(l, '==%s*Requests%s*for%s*other%s*global%s*permissions%s*==') ~= nil then -- We're going through the h2 section for other GPs.
b.a = true -- Use a boolean value to remark that.
end
if p.catch(l) ~= nil then -- Case 2 of p.match, which returns <username>[|<username>] and let us know if we're in a subsection.
b.b = true -- Subsection remarked.
b.c = p.ins(b.c, p.getun(p.catch(l))) -- Add the name caught to a table. This doesn't affect anything.
end
if b.a and b.b and mw.ustring.match(l, '%s*%|%s*status%s*=%s*.*') and not p.inc(p.status(l), s) then -- Get status.
list.GP.num = list.GP.num + 1 -- Found one, add it to our stock.
b.b = false -- No longer in subsection.
end
if mw.ustring.match(l, '==%s*.+%s*==<!--%s*.+%s*-->') ~= nil then -- This is meant to catch == See also == section.
b.a = false -- We're out of RfOGP, stop.
end
end
end
end
if frame then -- If a parameter was specified,
if frame.args[1] == 'GR' then -- outputs number of GR requests...
return list.GR.num
elseif frame.args[1] == 'GS' then -- ...GS...
return list.GS.num
elseif frame.args[1] == 'GRN' then -- ...GRN...
return list.GRN.num
elseif frame.args[1] == 'GP' then -- ...and the rest, accordingly.
return list.GP.num
end
else -- Else, returns a pipe-separated list.
local a = {} -- New table
for k, v in pairs(list) do
table.insert(a, list[k].num) -- Add all numbers to the table
end
return table.concat(a, '|')
end
end
function p.main() -- Main function
local num = mw.text.gsplit(p.list(), '|') -- p.list() returns a pipe-separated list (\d+|\d+|\d+|\d+); split it up.
local req = {}
local s = { -- "s" stands for `s`ection.
'Requests for global rename permissions',
'Requests for other global permissions',
'Requests for global sysop permissions',
'Requests for global rollback permissions'
}
local i = { -- Table for numbers.
t = { -- "t" stands for `t`rue.
0
},
f = { -- "f" stands for `f`alse.
0
},
i = 0 -- "i" stands for `i`ndex.
}
for n in num do -- Iterate "num".
i.i = i.i + 1 -- Add 1 to index before going.
if tonumber(n) > 0 then -- Outputs something is number of requests is not 0.
table.insert(req, '[[' .. title .. '#' .. s[i.i] .. '|' .. n .. ' Rf' .. perm[i.i] .. ']]')
table.insert(i.t, i.i) -- This is irrelevant; just ignore it.
else
table.insert(i.f, i.i) -- Idem.
end
end
if #req > 0 then -- If our total is not 0,
return ' • <b>' .. table.concat(req, '</b> • <b>') .. '</b>' -- ...adds requests up.
else
return '' -- No requests atm, return nothing.
end
end
function p.catch(l, list, k) -- This is meant to be a template for two cases: GR/GS/GRN and GP
local j -- Splitting cases
if list ~= nil
then j = 1
else
j = 2
end
if j == 1 then -- If case 1, everything this function needs were provided. Returns a value (which we don't have to care about) or nil.
return mw.ustring.match(l, '===%s*[Gg]lobal%s*' .. list[k].pat .. '%s*for%s*%[%[%s*[Uu][Ss][Ee][Rr]%s*:%s*..-%]%]%s*===')
else -- Returns <username>[|<username>]. Some people writes [[User:Foo]] instead of [[User:Foo|Foo]], hence the function.
return mw.ustring.match(l, '===%s*[^=]-for%s*%[%[%s*[Uu][Ss][Ee][Rr]%s*:%s*(..-)%]%][^=]-%s*===')
end
end
function p.status(str) -- Return value of |status= parameter, or the first word of the hidden comment <!--don't change this line-->.
return mw.ustring.lower(
mw.ustring.gsub(
mw.ustring.match(
mw.ustring.match(str, '%s*%|%s*status%s*=%s*(.*)'),
'([%w ]+)'
) or '',
'%s*',
''
)
)
end
function p.inc(e, a) -- Return a boolean value if "e" is an `e`lement (key/value) of table (`a`rray) "a".
local b = false
for k, v in pairs(a) do
if k == e or v == e then
b = true
end
end
return b
end
function p.split(str, sep) -- Splitting things up. "str" stands for `str`ing and "sep" stands for `sep`arator.
local t = {}
if sep == nil then
sep = '%s*([^|]+)%s*'
end
for str in string.gmatch(str, sep) do
table.insert(t, str)
end
return t
end
function p.getun(un, i) -- Outputs <username> from <username>[|<username>]. Generally this is irrelevant to our final result.
local id
if i ~= nil then
id = i
else
id = 1
end
return p.split(un)[id]:gsub('%s+', ' ')
end
function p.ins(a, e) -- Adds `e`lement "e" to `a`rray "a".
local i = #a
a[i+1] = e
return a
end
return p