| Vorlagenprogrammierung | Diskussionen | Lua | Test | Unterseiten | |||
| Modul | Deutsch | English
|
Modul: | Dokumentation | |||
Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus
2026-04-15local AccountUtl = { suite = "AccountUtl",
serial = "2026-04-15",
item = 139309150 }
--[=[
Utilities for user accounts.
isAnon()
isIP()
isTemp()
isUser()
isValid()
scope()
signer()
]=]
local Failsafe = AccountUtl
function isIP( account )
-- Check whether username is matching IPv4 scheme
-- Precondition:
-- account -- string, starting with nonzero digit
-- Postcondition:
-- Returns boolean
local sub = "([12]?[0-9]?[0-9])"
local seek = string.format( "^%s%%.%s%%.%s%%.%s$",
sub, sub, sub, sub )
local p1, p2, p3, p4 = account:match( seek )
if p1 and p2 and p3 and p4 then
local function legal( a )
if a:sub( 1, 1 ):find( "[1-9]" ) and
tonumber( a ) < 256 then
return true
end
end -- legal()
r = legal( p1 ) and
legal( p2 ) and
legal( p3 ) and
legal( p4 )
end
return r or false
end -- isIP()
function isTemp( account )
-- Check whether username is matching temporary scheme
-- Precondition:
-- account -- string, starting with "~"
-- Postcondition:
-- Returns boolean
local seek = "^~(20[2-9]%d)%-([1-9]%d%d%d[%d%-]*)$"
local y, s = account:match( seek )
if y then
y = tonumber( y )
if y >= 2024 then
local g
s = s .. "-"
g = s:match( "^(%d+)%-" )
if tonumber( g ) >= 1500 then
if s:match( "^%d+%-$" ) then
r = true
elseif g:len() == 5 then
s = s:sub( 7 )
g = s:match( "^(%d+)%-" )
if g then
local n = g:len()
if n <= 5 then
if s:match( "^%d+%-$" ) then
r = true
elseif n == 5 then
s = s:sub( 7 )
if s:match( "^%d+%-$" ) then
r = true
end
end
end
end
end
end
end
end
return r or false
end -- isTemp()
function isAnon( account )
-- Check whether username is matching IP or temporary scheme
-- Precondition:
-- account -- string
-- Postcondition:
-- Returns boolean
local s1 = account:sub( 1, 1 )
local r
if s1 == "~" then
r = isTemp( account )
elseif s1:find( "[1-9]" ) then
r = isIP( account )
end
return r or false
end -- isAnon()
function noIP( account )
-- Check whether lookalike username is not matching IPv4 scheme
-- Precondition:
-- account -- string, starting with digit
-- Postcondition:
-- Returns boolean, if not an IP
local sub = "(%d%d?%d?)"
local seek = string.format( "^%s%%.%s%%.%s%%.%s$",
sub, sub, sub, sub )
local p1, p2, p3, p4 = account:match( seek )
local r
if p1 and p2 and p3 and p4 then
local function lapsus( a )
if tonumber( a ) >= 256 then
return true
end
end -- lapsus()
r = lapsus( p1 ) or
lapsus( p2 ) or
lapsus( p3 ) or
lapsus( p4 )
else
r = true
end
return r
end -- noIP()
function isUser( account )
-- Check whether username might be any valid account
-- Precondition:
-- account -- string
-- Postcondition:
-- Returns boolean
local r
if isAnon( account ) then
r = true
elseif account:sub( 1, 1 ):find( "%d" ) then
r = noIP( account )
elseif account:sub( 1, 2 ) ~= "~2" then
r = true
end
return r or false
end -- isUser()
AccountUtl.isAnon = function ( account )
-- Check whether username is matching IP or temporary scheme
-- Precondition:
-- account -- string, or nil derived from current page
-- Postcondition:
-- Returns boolean
local s = AccountUtl.signer( account )
local r
if s then
r = isAnon( s )
end
return r or false
end -- AccountUtl.isAnon()
AccountUtl.isIP = function ( account )
-- Check whether username is matching IPv4 scheme
-- Precondition:
-- account -- string, or nil derived from current page
-- Postcondition:
-- Returns boolean
local s = AccountUtl.signer( account )
local r
if s then
if s:sub( 1, 1 ):find( "[1-9]" ) then
r = isIP( s )
end
end
return r or false
end -- AccountUtl.isIP()
AccountUtl.isTemp = function ( account )
-- Check whether username is matching temporary scheme
-- Precondition:
-- account -- string, or nil derived from current page
-- Postcondition:
-- Returns boolean
local s = AccountUtl.signer( account )
local r
if s then
if s:sub( 1, 1 ) == "~" then
local seek = "^~(20[2-9]%d)%-([1-9]%d%d%d[%d%-]*)$"
local y
y, s = s:match( seek )
if y then
y = tonumber( y )
if y >= 2024 then
local g
s = s .. "-"
g = s:match( "^(%d+)%-" )
if tonumber( g ) >= 1500 then
if s:match( "^%d+%-$" ) then
r = true
elseif g:len() == 5 then
s = s:sub( 7 )
g = s:match( "^(%d+)%-" )
if g then
local n = g:len()
if n <= 5 then
if s:match( "^%d+%-$" ) then
r = true
elseif n == 5 then
s = s:sub( 7 )
if s:match( "^%d+%-$" ) then
r = true
end
end
end
end
end
end
end
end
end
end
return r or false
end -- AccountUtl.isTemp()
AccountUtl.isUser = function ( account )
-- Check whether username might be any valid account
-- Precondition:
-- account -- string, or nil derived from current page
-- Postcondition:
-- Returns boolean
local r
if AccountUtl.signer( account ) then
r = true
end
return r or false
end -- AccountUtl.isUser()
AccountUtl.isValid = function ( account )
-- Check whether username can be used as nick for registration
-- Precondition:
-- account -- string, or nil derived from current page
-- Postcondition:
-- Returns boolean
local s = AccountUtl.signer( account )
local r
if s then
if not isAnon( s ) then
if s:sub( 1, 1 ):find( "%d" ) then
r = noIP( s )
else
r = true
end
end
end
return r or false
end -- AccountUtl.isValid()
AccountUtl.scope = function ( account )
-- Identify the type of a presumed account name
-- Precondition:
-- account -- string, or nil derived from current page
-- Postcondition:
-- Returns string, or false
-- "R" -- registered
-- "I" -- IP
-- "T" -- temporary
local s = AccountUtl.signer( account )
local r
if s then
local s1 = s:sub( 1, 1 )
r = "R"
if s1 == "~" then
if isTemp( s ) then
r = "T"
elseif s:sub( 2, 2 ) == "2" then
r = false
end
elseif s1:find( "[1-9]" ) then
if isIP( s ) then
r = "I"
elseif noIP( s ) then
r = false
end
end
end
return r or false
end -- AccountUtl.scope()
AccountUtl.signer = function ( adjust )
-- Normalize username string, or derive from page
-- Precondition:
-- adjust -- string, or not
-- Postcondition:
-- Returns normalized string of a username, or not
local r = adjust
local scan
if type( r ) == "string" then
if r:find( "&", 1, true ) then
r = mw.text.decode( r )
if r:find( "&#?[%a]+;" ) then
r = mw.text.decode( r, true )
end
end
scan = string.format( "[_%%s%c]+", 0x0A )
r = mw.ustring.gsub( r, scan, " " )
r = mw.text.trim( r )
if r == "" then
r = false
elseif r:find( ":", 2, true ) then
local s1, s2 = mw.ustring.match( r, "^([^:]+):(.+)$" )
if s1 then
local o = mw.site.namespaces[ s1 ]
if o then
local n = o.id
if n == 2 or n == 3 then
r = mw.text.trim( s2 )
n = r:find( "/", 1, true )
if n then
if n == 1 then
r = false
else
r = mw.text.trim( r:sub( 1, n - 1 ) )
end
end
end
end
end
end
end
if type( r ) == "string" then
if mw.ustring.len( r ) > 255 then
r = false
-- mw:Manual:$wgMaxNameChars MW 1.2...1.4: 32
else
scan = "[@#<>|%[%]%{%}:/]"
-- mw:Manual:$wgInvalidUsernameCharacters
if mw.ustring.find( r, scan ) or
not isUser( r ) then
r = false
end
end
else
local t = mw.title.getCurrentTitle()
if t.namespace == 2 or t.namespace == 3 then
r = t.rootText
if isUser( r ) then
if mw.ustring.find( r, "@<>:" ) or
mw.ustring.len( r ) > 255 then
r = false
end
else
r = false
end
else
r = false
end
end
return r
end -- AccountUtl.signer()
Failsafe.failsafe = function ( atleast )
-- Retrieve versioning and check for compliance
-- Precondition:
-- atleast -- string, with required version
-- or wikidata|item|~|@ or false
-- Postcondition:
-- Returns string -- with queried version/item, also if problem
-- false -- if appropriate
-- 2024-03-01
local since = atleast
local last = ( since == "~" )
local linked = ( since == "@" )
local link = ( since == "item" )
local r
if last or link or linked or since == "wikidata" then
local item = Failsafe.item
since = false
if type( item ) == "number" and item > 0 then
local suited = string.format( "Q%d", item )
if link then
r = suited
else
local entity = mw.wikibase.getEntity( suited )
if type( entity ) == "table" then
local seek = Failsafe.serialProperty or "P348"
local vsn = entity:formatPropertyValues( seek )
if type( vsn ) == "table" and
type( vsn.value ) == "string" and
vsn.value ~= "" then
if last and vsn.value == Failsafe.serial then
r = false
elseif linked then
if mw.title.getCurrentTitle().prefixedText
== mw.wikibase.getSitelink( suited ) then
r = false
else
r = suited
end
else
r = vsn.value
end
end
end
end
elseif link then
r = false
end
end
if type( r ) == "nil" then
if not since or since <= Failsafe.serial then
r = Failsafe.serial
else
r = false
end
end
return r
end -- Failsafe.failsafe()
-- Export
local p = { }
function is( access, frame )
return AccountUtl[ access ]( frame.args[ 1 ] ) and "1" or ""
end -- is()
function p.isAnon( frame )
return is( "isAnon", frame )
end -- p.isAnon
function p.isIP( frame )
return is( "isIP", frame )
end -- p.isIP
function p.isTemp( frame )
return is( "isTemp", frame )
end -- p.isTemp
function p.isUser( frame )
return is( "isUser", frame )
end -- p.isUser
function p.isValid( frame )
return is( "isValid", frame )
end -- p.isValid
function p.scope( frame )
return AccountUtl.scope( frame.args[ 1 ] )
end -- p.scope
function p.signer( frame )
return AccountUtl.signer( frame.args[ 1 ] )
end -- p.signer
p.failsafe = function ( frame )
-- Versioning interface
local s = type( frame )
local since
if s == "table" then
since = frame.args[ 1 ]
elseif s == "string" then
since = frame
end
if since then
since = mw.text.trim( since )
if since == "" then
since = false
end
end
return Failsafe.failsafe( since ) or ""
end -- p.failsafe
setmetatable( p, { __call = function ( func, ... )
setmetatable( p, nil )
return Failsafe
end } )
return p
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.