Jump to content
 







Main menu
   


Navigation  



Main page
Contents
Current events
Random article
About Wikipedia
Contact us
Donate
 




Contribute  



Help
Learn to edit
Community portal
Recent changes
Upload file
 








Search  

































Create account

Log in
 









Create account
 Log in
 




Pages for logged out editors learn more  



Contributions
Talk
 



















Contents

   



(Top)
 


1 Creating new objects  





2 Methods and properties  





3 Expensive functions  














Module:Rfx






تۆرکجه

Cebuano
فارسی


 

Edit links
 









Module
Talk
 

















Read
View source
View history
 








Tools
   


Actions  



Read
View source
View history
 




General  



What links here
Related changes
Upload file
Special pages
Permanent link
Page information
Get shortened URL
Download QR code
Wikidata item
 




Print/export  



Download as PDF
Printable version
 
















Appearance
   

 





Permanently protected module

From Wikipedia, the free encyclopedia
 


This is a library for getting information about individual requests for adminship (RfA) and requests for bureaucratship (RfB) pages on the English Wikipedia. It is not meant to be used directly from wiki pages, but rather to be used by other Lua modules.

Creating new objects

First of all, the library must be loaded, like this:

local rfx = require( 'Module:Rfx' )

Once the library is loaded, you can make a new rfx object using rfx.new(). Caution - this function is expensive (see below).

rfx.new() is used like this:

local myRfx = rfx.new( pagename )

The pagename variable should be the name of a valid RfA or RfB page, for example:

local exampleRfa = rfx.new( 'Wikipedia:Requests for adminship/Example' )

Ifpagename is not specified, or the page is not a subpage of Wikipedia:Requests for adminshiporWikipedia:Requests for bureaucratship, then rfx.new will return nil.

Methods and properties

Once you have created a new rfx object, there are a number of methods and properties that you can use. They are all read-only.

Properties
Methods

Methods must be called with the colon syntax:

local titleObject = exampleRfa:getTitleObject()

You can compare rfx objects with the == operator. This will return true only if the two objects point to the same page. tostring( rfx ) will return prefixedTitle from the RfX page's title object (see the reference manual).

Expensive functions

This module makes use of the title:getContent method to fetch RfX page sources. This method will be called for each RfX page being looked up, so each use of rfx.new will count as an expensive function call. Please be aware that the library may fail for scripts which create many different RfX objects. (The current limit for the English Wikipedia is 500 expensive function calls per page.) Also, each RfX page that is looked up will count as a transclusioninSpecial:WhatLinksHere.

----------------------------------------------------------------------
--                          Module:Rfx                              --
-- This is a library for retrieving information about requests      --
-- for adminship and requests for bureaucratship on the English     --
-- Wikipedia. Please see the module documentation for instructions. --
----------------------------------------------------------------------

local libraryUtil = require('libraryUtil')
local lang = mw.getContentLanguage()
local textSplit = mw.text.split
local umatch = mw.ustring.match
local newTitle = mw.title.new

local rfx = {}

--------------------------------------
--         Helper functions         --
--------------------------------------

local function getTitleObject(title)
 local success, titleObject = pcall(newTitle, title)
 if success and titleObject then
  return titleObject
 else
  return nil
 end
end

local function parseVoteBoundaries(section)
 -- Returns an array containing the raw wikitext of RfX votes in a given section.
 section = section:match('^.-\n#(.*)$') -- Strip non-votes from the start.
 if not section then
  return {}
 end
 section = section:match('^(.-)\n[^#]') or section -- Discard subsequent numbered lists.
 local comments = textSplit(section, '\n#')
 local votes = {}
 for i, comment in ipairs(comments) do
  if comment:find('^[^#*;:].*%S') then
   votes[#votes + 1] = comment
  end
 end
 return votes
end

local function parseVote(vote)
 -- parses a username from an RfX vote.
 local userStart, userMatch = vote:match('^(.*)%[%[[%s_]*:?[%s_]*[uU][sS][eE][rR][%s_]*:[%s_]*(.-)[%s_]*%]%].-$')
 local talkStart, talkMatch = vote:match('^(.*)%[%[[%s_]*:?[%s_]*[uU][sS][eE][rR][%s_]+[tT][aA][lL][kK][%s_]*:[%s_]*(.-)[%s_]*%]%].-$')
 local contribStart, contribMatch = vote:match('^(.*)%[%[[%s_]*:?[%s_]*[sS][pP][eE][cC][iI][aA][lL][%s_]*:[%s_]*[cC][oO][nN][tT][rR][iI][bB][uU][tT][iI][oO][nN][sS]/[%s_]*(.-)[%s_]*%]%].-$')
 local username
 if userStart and talkStart then
  if #userStart > #talkStart then
   username = userMatch
  else
   username = talkMatch
  end
 elseif userStart then
  username = userMatch
 elseif talkStart then
  username = talkMatch
 elseif contribStart then
  username = contribMatch
 else
  return string.format( "'''Error parsing signature''': ''%s''", vote )
 end
 username = username:match('^[^|/#]*')
 return username
end

local function parseVoters(votes)
 local voters = {}
 for i, vote in ipairs(votes) do
  voters[#voters + 1] = parseVote(vote)
 end
 return voters
end

local function dupesExist(...)
 local exists = {}
 local tables = {...}
 for i, usernames in ipairs(tables) do
  for j, username in ipairs(usernames) do
   username = lang:ucfirst(username)
   if exists[username] then
    return true
   else
    exists[username] = true
   end
  end
 end
 return false
end

------------------------------------------
--   Define the constructor function    --
------------------------------------------

function rfx.new(title)
 local obj = {}
 local data = {}
 local checkSelf = libraryUtil.makeCheckSelfFunction( 'Module:Rfx', 'rfx', obj, 'rfx object' )
 
 -- Get the title object and check to see whether we are a subpage of WP:RFA or WP:RFB.
 title = getTitleObject(title)
 if not title then
  return nil
 end
 
 function data:getTitleObject()
  checkSelf(self, 'getTitleObject')
  return title
 end
 
 if title.namespace == 4 then
  local rootText = title.rootText
  if rootText == 'Requests for adminship' then
   data.type = 'rfa'
  elseif rootText == 'Requests for bureaucratship' then
   data.type = 'rfb'
  else
   return nil
  end
 else
  return nil
 end

 -- Get the page content and divide it into sections.
 local pageText = title:getContent()
 if not pageText then
  return nil
 end
 local introText, supportText, opposeText, neutralText = umatch(
  pageText,
  '^(.-)\n====[^=\n][^\n]-====.-'
  .. '\n=====%s*[sS]upport%s*=====(.-)'
  .. '\n=====%s*[oO]ppose%s*=====(.-)'
  .. '\n=====%s*[nN]eutral%s*=====(.-)$'
 )
 if not introText then
  introText, supportText, opposeText, neutralText = umatch(
   pageText,
   "^(.-\n'''[^\n]-%(%d+/%d+/%d+%)[^\n]-''')\n.-"
   .. "\n'''Support'''(.-)\n'''Oppose'''(.-)\n'''Neutral'''(.-)"
  )
 end

 -- Get vote counts.
 local supportVotes, opposeVotes, neutralVotes
 if supportText and opposeText and neutralText then
  supportVotes = parseVoteBoundaries(supportText)
  opposeVotes = parseVoteBoundaries(opposeText)
  neutralVotes = parseVoteBoundaries(neutralText)
 end
 local supports, opposes, neutrals
 if supportVotes and opposeVotes and neutralVotes then
  supports = #supportVotes
  data.supports = supports
  opposes = #opposeVotes
  data.opposes = opposes
  neutrals = #neutralVotes
  data.neutrals = neutrals
 end

 -- Voter methods and dupe check.

 function data:getSupportUsers()
  checkSelf(self, 'getSupportUsers')
  if supportVotes then
   return parseVoters(supportVotes)
  else
   return nil
  end
 end

 function data:getOpposeUsers()
  checkSelf(self, 'getOpposeUsers')
  if opposeVotes then
   return parseVoters(opposeVotes)
  else
   return nil
  end
 end

 function data:getNeutralUsers()
  checkSelf(self, 'getNeutralUsers')
  if neutralVotes then
   return parseVoters(neutralVotes)
  else
   return nil
  end
 end

 function data:dupesExist()
  checkSelf(self, 'dupesExist')
  local supportUsers = self:getSupportUsers()
  local opposeUsers = self:getOpposeUsers()
  local neutralUsers = self:getNeutralUsers()
  if not (supportUsers and opposeUsers and neutralUsers) then
   return nil
  end
  return dupesExist(supportUsers, opposeUsers, neutralUsers)
 end

 if supports and opposes then
  local total = supports + opposes
  if total <= 0 then
   data.percent = 0
  else
   data.percent = math.floor((supports / total * 100) + 0.5)
  end
 end
 if introText then
  data.endTime = umatch(introText, '(%d%d:%d%d, %d+ %w+ %d+) %(UTC%)')
  data.user = umatch(introText, '===%s*%[%[[_%s]*[wW]ikipedia[_%s]*:[_%s]*[rR]equests[_ ]for[_ ]%w+/.-|[_%s]*(.-)[_%s]*%]%][_%s]*===')
  if not data.user then
   data.user = umatch(introText, '===%s*([^\n]-)%s*===')
  end
 end
 
 -- Methods for seconds left and time left.
 
 function data:getSecondsLeft()
  checkSelf(self, 'getSecondsLeft')
  local endTime = self.endTime
  if not endTime then
   return nil
  end
  local now = tonumber(lang:formatDate("U"))
  local success, endTimeU = pcall(lang.formatDate, lang, 'U', endTime)
  if not success then
   return nil
  end
  endTimeU = tonumber(endTimeU)
  if not endTimeU then
   return nil
  end
  local secondsLeft = endTimeU - now
  if secondsLeft <= 0 then
   return 0
  else
   return secondsLeft
  end
 end

 function data:getTimeLeft()
  checkSelf(self, 'getTimeLeft')
  local secondsLeft = self:getSecondsLeft()
  if not secondsLeft then
   return nil
  end
  return mw.ustring.gsub(lang:formatDuration(secondsLeft, {'days', 'hours'}), ' and', ',')
 end
 
 function data:getReport()
  -- Gets the URI object for Vote History tool
  checkSelf(self, 'getReport')
  return mw.uri.new('https://apersonbot.toolforge.org/vote-history?page=' .. mw.uri.encode(title.prefixedText))
 end
 
 function data:getStatus()
  -- Gets the current status of the RfX. Returns either "successful", "unsuccessful",
  -- "discussion", "open", or "pending closure". Returns nil if the status could not be found.
  checkSelf( self, 'getStatus' )
  local rfxType = data.type
  if rfxType == 'rfa' then
   if umatch(
    pageText,
    '%[%[[%s_]*[cC][aA][tT][eE][gG][oO][rR][yY][%s_]*:[%s_]*[sS]uccessful requests for adminship(.-)[%s_]*%]%]'
   ) then
    return 'successful'
   elseif umatch(
    pageText,
    '%[%[[%s_]*[cC][aA][tT][eE][gG][oO][rR][yY][%s_]*:[%s_]*[uU]nsuccessful requests for adminship(.-)[%s_]*%]%]'
   ) then
    return 'unsuccessful'
   end
  elseif rfxType == 'rfb' then
   if umatch(
    pageText,
    '%[%[[%s_]*[cC][aA][tT][eE][gG][oO][rR][yY][%s_]*:[%s_]*[sS]uccessful requests for bureaucratship(.-)[%s_]*%]%]'
   ) then
    return 'successful'
   elseif umatch(
    pageText,
    '%[%[[%s_]*[cC][aA][tT][eE][gG][oO][rR][yY][%s_]*:[%s_]*[uU]nsuccessful requests for bureaucratship(.-)[%s_]*%]%]'
   ) then
    return 'unsuccessful'
   end
  end
  local secondsLeft = self:getSecondsLeft()
  if secondsLeft and secondsLeft > 432000 then -- Per 2023 Phase I Proposal 3b: the voting period is for the final 5 days
   return 'discussion'
  elseif secondsLeft and secondsLeft > 0 then
   return 'open'
  elseif secondsLeft and secondsLeft <= 0 then
   return 'pending closure'
  else
   return nil
  end
 end
 
 -- Specify which fields are read-only, and prepare the metatable.
 local readOnlyFields = {
  getTitleObject = true,
  ['type'] = true,
  getSupportUsers = true,
  getOpposeUsers = true,
  getNeutralUsers = true,
  supports = true,
  opposes = true,
  neutrals = true,
  endTime = true,
  percent = true,
  user = true,
  dupesExist = true,
  getSecondsLeft = true,
  getTimeLeft = true,
  getReport = true,
  getStatus = true
 }
 
 local function pairsfunc( t, k )
  local v
  repeat
   k = next( readOnlyFields, k )
   if k == nil then
    return nil
   end
   v = t[k]
  until v ~= nil
  return k, v
 end

 return setmetatable( obj, {
  __pairs = function ( t )
   return pairsfunc, t, nil
  end,
  __index = data,
  __newindex = function( t, key, value )
   if readOnlyFields[ key ] then
    error( 'index "' .. key .. '" is read-only', 2 )
   else
    rawset( t, key, value )
   end
  end,
  __tostring = function( t )
   return t:getTitleObject().prefixedText
  end
 } )
end

return rfx

Retrieved from "https://en.wikipedia.org/w/index.php?title=Module:Rfx&oldid=1227492580"

Category: 
Modules for general use
Hidden category: 
Wikipedia semi-protected modules
 



This page was last edited on 6 June 2024, at 01:38 (UTC).

Text is available under the Creative Commons Attribution-ShareAlike License 4.0; additional terms may apply. By using this site, you agree to the Terms of Use and Privacy Policy. Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc., a non-profit organization.



Privacy policy

About Wikipedia

Disclaimers

Contact Wikipedia

Code of Conduct

Developers

Statistics

Cookie statement

Mobile view



Wikimedia Foundation
Powered by MediaWiki