Module:Unsigned
Appearance
| This module is rated as beta. It is considered ready for widespread use, but as it is still relatively new, it should be applied with some caution to ensure results are as expected. |
| This module is currently protected from editing. See the protection policy and protection log for more details. Please discuss any changes on the talk page; you may submit an edit request to ask an administrator to make an edit if it is uncontroversial or supported by consensus. You may also request that this page be unprotected. |
| This module depends on the following other modules: |
This module implements {{unsigned}}. It has a few functions:
maincalled by {{unsigned}}; not intended for broader usegetTimestampfind a timestamp from a string. If only a date is found, it returns the date. If only a time is found, it returns the empty string. If a time and a date are both found, it appends(UTC)
.getUsernamegets the username from a string containing a timestamp. It currently assumes that everything besides a timestamp is part of the username.
local p = {}
local yesno = require('Module:Yesno')
local function trim(s)
return s:gsub("^%s+", ""):gsub("%s+$", ""):gsub("\226\128\142", "")
end
function p.getTimestamp(s)
--gets the timestamp in the input
--if nothing is found, returns the empty string
--we search for time and date seperately to allow for a time-less addition of date
-- helper to search the input string
-- note that match on nil is a bad thing, so we include: or ''
local function findFromInput(target)
return mw.ustring.match( s or '', target, 0)
end
-- find the date
local theDate =
findFromInput('%d%d? %u%l+ %d%d%d%d') -- DMY
or findFromInput('%u%l+ %d%d?, %d%d%d%d') -- MDY
or findFromInput('%d%d%d%d %u%l+ %d%d?') -- YMD
or findFromInput('%d%d%d%d%-%d%d%-%d%dT%d%d:%d%d:%d%d') -- 2025-06-28T19:49:51 style
if theDate then
-- we have a date, so process and return accordingly
-- first sanitize the date
theDate = require('Module:Format time')._main{theDate}
-- then check if there is a timestamp
local theTime = findFromInput('%d%d:%d%d')
return theTime and (theTime .. ', ' .. theDate .. ' (UTC)') or theDate
else
return ''
end
end
function p.getUsername(s)
--gets the username in the input
--------WARNING--------
--this method assumes that *everything* besides the timestamp is, in fact, part of the username
--it does no further username validation
--if you try putting random garbage in, you **will** get garbage out
--------YOU HAVE BEEN WARNED--------
-- if nil, then return the empty string
if not s then return '' end
local toReturn = s
-- Patterns matching various timestamp formats
local patterns = {
'%d%d%d%d%-%d%d%-%d%dT%d%d:%d%d:%d%d', -- Timestamp: e.g., 2025-06-28T19:49:51
'%d%d? %u%l+ %d%d%d%d', -- DMY: e.g., 25 June 2025
'%u%l+ %d%d?, %d%d%d%d', -- MDY: e.g., June 25, 2025
'%d%d%d%d %u%l+ %d%d?', -- YMD: e.g., 2025 June 25
'%d%d:%d%d,?', -- Time: e.g., 19:32,
'%(UTC%)', -- UTC marker
}
for _, pattern in ipairs(patterns) do
toReturn = mw.ustring.gsub(toReturn, pattern, '', 1)
end
--concat the empty string to ensure we only return the string and not the number of matches
return trim(toReturn) .. ''
end
local function makeUnsigned(args)
local username
local timestamp
if args[2] then
-- we have multiple parameters
-- so we can be less janky
timestamp = p.getTimestamp(args[2])
if timestamp ~= '' then
username = trim(args[1] or '')
else
username = trim(args[2] or '')
timestamp = p.getTimestamp(args[1]) -- necessary to append (UTC) if needed
end
else
-- be very janky; this has a high probability of GIGO-ing
-- due to the way getUsername is implemented
username = p.getUsername(args[1])
timestamp = p.getTimestamp(args[1])
end
-- error if we cannot find a username
if username == '' then
return '<em class="error">Unable to detect username</em>'
end
return mw.getCurrentFrame():expandTemplate{
title = require('Module:IPAddress')._isIp(username) and 'unsigned/unregistered' or 'unsigned/registered',
args = {
username,
timestamp,
fix = yesno(args.fix) and 'yes' or ''
}
}
end
function p.main(frame)
local args
if type(frame.args) == 'table' then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
args = require('Module:Arguments').getArgs(frame)
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
end
return makeUnsigned(args)
end
return p