Jump to content

Module:Votings/sandbox

From Meta, a Wikimedia project coordination wiki
Module documentation

Usage

[edit]

See Template:Votings.


-- For attribution: [[:vi:Module:CurrentCandidateList]]
require('strict')

local p = {}

local rfa_page_name = 'Meta:Requests for adminship'
local rfa_page_content = mw.title.new(rfa_page_name):getContent() --[[@as string]]

---@class PermissionInfo
---@field acronym string
---@field base_page_name string
---@field section_name? string

---@type PermissionInfo[]
local permissions = {
	{
		acronym = 'A',
		base_page_name = 'adminship',
		section_name = 'regular adminship'
	},
	{
		acronym = 'LA',
		base_page_name = 'limited adminship'
	},
	{
		acronym = 'IA',
		base_page_name = 'interface adminship'
	},
	{
		acronym = 'B',
		base_page_name = 'bureaucratship'
	},
	{
		acronym = 'CU',
		base_page_name = 'checkuser',
		section_name = 'CheckUser access'
	},
	{
		acronym = 'OS',
		base_page_name = 'oversight',
		section_name = 'Oversight access'
	},
	{
		acronym = 'TA',
		base_page_name = 'translation adminship'
	},
	{
		acronym = 'CN',
		base_page_name = 'CentralNotice adminship'
	},
	{
		acronym = 'BF',
		base_page_name = 'bot status',
		section_name = 'bot flags'
	}
}

---Whether `table` contains `value`.
---
---@param table any[]
---@param value any
---@return boolean
local function _table_includes(table, value)
	for _, element in ipairs(table) do
		if element == value then
			return true
		end
	end

	return false
end

---Return a list of all request subpages that are transcluded onto the main page.
---
---@return string[]
function p._find_request_page_names()
	---@type string[]
	local page_names = {}

	local exemptions = {
		'none', 'None', 'rF', 'RF',
		'Meta:Requests for bot status/Examplebot',
		'Meta:Requests for translation adminship/ExampleUser'
	}
	local transcluded_page_name = '%{%{([^#|<>{}%[%]]+)%}%}'

	for line in mw.text.gsplit(rfa_page_content, '\n') do
		local trimmed_line = mw.text.trim(line)
		local page_name = mw.ustring.match(trimmed_line, transcluded_page_name)

		if page_name and not _table_includes(exemptions, page_name) then
			table.insert(page_names, page_name)
		end
	end

	return page_names
end

---Given a request subpage's full name,
---return the corresponding permission acronym
---and the rightmost part of the title.
---
---@param page_name string # A request subpage's name
---@return string?, string?
function p._parse_request_page_name(page_name)
	local normalized_page_name = mw.title.new(page_name).fullText

	for _, permission in ipairs(permissions) do
		local expected_prefix = 'Meta:Requests for ' .. permission.base_page_name .. '/'

		if (
			#normalized_page_name > #expected_prefix and
			mw.ustring.sub(normalized_page_name, 1, #expected_prefix) == expected_prefix
		) then
			local subpage_name = mw.ustring.sub(normalized_page_name, #expected_prefix + 1)

			return permission.acronym, subpage_name
		end
	end

	return nil, nil
end

---Put request page names into corresponding subtables of a table.
---
---@param request_page_names string[]
---@return table<string, string[]>
function p._collect_requests(request_page_names)
	---@type table<string, string[]>
	local acronym_to_subpage_names = {}

	for _, permission in ipairs(permissions) do
		acronym_to_subpage_names[permission.acronym] = {}
	end

	for _, request_page_name in ipairs(request_page_names) do
		local acronym, subpage_name = p._parse_request_page_name(request_page_name)

		if acronym and subpage_name then
			table.insert(acronym_to_subpage_names[acronym], subpage_name)
		end
	end

	return acronym_to_subpage_names
end

---Convert the table returned by `p._count_requests`
---to a human-readable horizontal list.
---
---@param counts table<string, string[]>
---@return string
function p._join_to_human_readable_list(counts)
	local links = {}

	for _, permission in ipairs(permissions) do
		local acronym = permission.acronym
		local section_name = permission.section_name or permission.base_page_name
		local count = #counts[acronym]

		if count > 0 then
			local link_to_section = rfa_page_name .. '#Requests for ' .. section_name
			local link_text = count .. '&nbsp;Rf' .. acronym
			local link = '[[' .. link_to_section .. '|' .. link_text .. ']]'

			table.insert(links, '&nbsp;&bull; <b>' .. link .. '</b>')
		end
	end

	return table.concat(links, '')
end

function p.main()
	local request_page_names = p._find_request_page_names()
	local request_counts = p._collect_requests(request_page_names)

	return p._join_to_human_readable_list(request_counts)
end

return p