Modul:Pinging

aus Wikipedia, der freien Enzyklopädie
local Serial = "2015-12-22"
--[=[
Module:Pinging -- Support templates for pings and user lists
]=]



-- local globals
local MaxEcho = 50    -- currently permitted number of recipients
local MaxName = 34    -- length of a user name
local Start   = "@"
local Stick   = "<span style='white-space:nowrap'> </span>| "
local Suffix  = ":"



local function fair( analyse, add )
    -- Create link target or link title
    -- Parameter:
    --     analyse  -- string with page name or nick
    --     add      -- true, if user namespace to be added
    --                 false, if user namespace to be stripped
    -- Returns:
    --     string
    local ns = false
    local r  = analyse
    local space, spec = r:match( "^([^:]+):(.+)$" )
    if space then
        local tns = mw.site.namespaces[ space ]
        if type( tns ) == "table" then
            ns = tns.id
        end
    end
    if add then
        if not ns then
            r = string.format( "%s:%s", mw.site.namespaces.User.name, r )
        end
    elseif ns then
        if ns == 2  or  ns == 3 then
            r = spec
        end
    end
    return r
end -- fair()



local function fault( alert )
    -- Format error message by class=error
    -- Parameter:
    --     alert  -- string, error message
    -- Returns:
    --     string, HTML span
    return string.format( "<span %s %s>%s</span>",
                          "class=\"error\"",
                          "style='white-space:nowrap'",
                          alert );
end -- fault()



local function fetch( analyse )
    -- Retrieve target table
    -- Parameter:
    --     analyse  -- string with page content
    -- Returns:
    --     sequence of targets, even empty
    local i    = 1
    local loop = true
    local r    = { }
    local s    = analyse
    local j, k
    while ( loop ) do
        loop = false
        j    = s:find( "<!--", i, true )
        if j then
            k = s:find( "-->",  j + 4,  true )
            if k then
                loop = true
                s    = s:sub( 1,  j )  ..  s:sub( k + 3 )
                i    = j
            end
        end
    end -- while loop
    i    = 1
    loop = true
    while ( loop ) do
        loop = false
        j    = s:find( "{{#target:", i, true )
        if j then
            j = j + 10
            k = s:find( "}}", j, true )
            if k then
                loop = true
                table.insert( r,  s:sub( j,  k - 1 ) )
                i = k + 1
            end
        end
    end -- while loop
    return r
end -- fetch()



local function friend( assign, abroad, area, another, alter )
    -- Format single link
    -- Parameter:
    --     assign   -- user or page name
    --     abroad   -- page names came from #target
    --     area     -- true: always wide area = URL
    --     another  -- display alternative link title
    --     alter    -- link is hidden
    -- Returns:
    --     1. string or false,
    --     2. true: string is internal
    --     3. true: error occurred
    local long = area
    local r    = assign
    local site = false
    local lapsus
    if abroad then
        local s
        s, site = assign:match( "^%s*(.+)%s*|%s*(.*)%s*$" )
        if s then
           site = mw.text.trim( site )
           if site == "" then
               site = false
           else
               long = true
           end
           r = s
        end
    end
    if r then
        r = mw.text.trim( r )
        if r == "" then
            r = false
        end
    end
    if r then
        local live = not alter
        local show
        if r:find( "[#<>%[%]%{%}]" )    or
           ( not abroad   and
             ( r:find( "[/@]" )   or
               mw.ustring.len( r ) > MaxName) ) then
            lapsus = true
        end
        if not lapsus then
            if another then
                show = mw.text.trim( another )
                if show == "" then
                    show = false
                end
            elseif live then
                show = fair( r, false )
            end
        end
        if not show then
            show = r
        end
        if abroad then
            if site then
                show = string.format( "%s@%s", show, site )
            end
        else
            r = fair( r, true )
        end
        if show:find( "%s" )  and  live then
            show = mw.text.trim( show )
            if show:find( "%s" ) then
                show = string.format( "<span %s>%s</span>",
                                      "style='white-space:nowrap'",
                                      show )
            end
        end
        if lapsus then
            r    = fault( show )
            long = true
        elseif long then
            if site then
                r = string.format( "//%s/wiki/%s",
                                   site,
                                   mw.uri.encode( r, "WIKI" ) )
            else
                r = tostring( mw.uri.canonicalUrl( r ) )
            end
            r = string.format( "[%s %s]", r, show )
            if live then
                r = string.format( "<span class='plainlinks'>%s</span>",
                                   r )
            end
        elseif alter  or  r == show then
            r = string.format( "[[%s]]", r )
        else
            r = string.format( "[[%s|%s]]", r, show )
        end
    end
    return r,  not long,  lapsus
end -- friend()



local function friends( assigned, abroad, area, assume, active, alter )
    -- Make list of entries
    -- Parameter:
    --     assigned  -- table with pages or users
    --     abroad    -- true: page names came from #target
    --     area      -- true: always wide area = URL
    --     assume    -- table with default options
    --     active    -- table with current options
    --     alter     -- string: hide result, show this
    -- Returns:
    --     string
    local limit  = ( not area  and
                     active.max ~= "0"  and  assume.max ~= "0" )
    local max    = MaxEcho
    local n      = 0
    local stick  = Stick
    local lapsus, light, lost, r, s
    if alter then
        stick = " "
    elseif active[ "/" ] then
        stick = active[ "/" ]
    elseif assume[ "/" ] then
        stick = assume[ "/" ]
    end
    if limit  and  ( active.max or assume.max ) then
        if tonumber( assume.max ) then
            max = tonumber( assume.max )
        end
        if tonumber( active.max ) then
            max = tonumber( active.max )
        end
    end
    stick = stick:gsub( "^_", " " )
                 :gsub( "_$", " " )
    for k, v in pairs( assigned ) do
        if type( k ) == "number" then
            s = assigned[ "label" .. tostring( k ) ]
            s, light, lost = friend( v, abroad, area, s, alter )
            if s then
                if r then
                    r = r .. stick
                else
                    r = ""
                end
                if lost then
                    lapsus = true
                elseif limit and light then
                    n = n + 1
                    if n > max then
                        local scream = "Echo-notification-count"
                        scream = mw.message.new( scream )
                        scream = scream:numParams( max )
                                       :plain()
                        scream = string.format( "&#32;!! %s !!&#32;",
                                                scream )
                        r      = r .. fault( scream )
                        lapsus = true
                        limit  = false
                    end
                end
                r = r .. s
            end
        end
    end -- for k
    if r then
        local start  = Start
        local suffix = Suffix
        if active[ "@" ] then
            start = active[ "@" ]
        elseif assume[ "@" ] then
            start = assume[ "@" ]
        elseif active.a then
            start = active.a
        end
        if active[ ":" ] then
            suffix = active[ ":" ]
        elseif active.p then
            suffix = active.p
        elseif assume[ ":" ] then
            suffix = assume[ ":" ]
        end
        start = start:gsub( "^_", " " )
                     :gsub( "_$", " " )
        suffix = suffix:gsub( "^_", " " )
                       :gsub( "_$", " " )
        if alter  and  not lapsus then
            r = string.format( "<span %s>%s</span>%s",
                               "style='display:none'",
                               r, alter )
        end
        r = string.format( "%s%s%s", start, r, suffix )
    else
        r = fault( "? . ? . ? . ?" )
    end
    return r
end -- friends()



local function massmessage( assume, active )
    -- Create text from massmessage distribution page
    -- Parameter:
    --     assume  -- table with default options
    --                [ 1 ]  -- page speification
    --                [ 2 ]  -- title; none for "_", list if omitted
    --     active  -- table with current options
    -- Returns:
    --     string
    local source = assume[ 1 ]
    local page, r, targets
    if source then
        local id, story
        id = source:match( "^%s*#(%d+)%s*$" )
        if id then
            page = tonumber( id )
        else
            page = source
        end
        page = mw.title.new( page )
        if page then
            story = page:getContent()
        end
        if story then
            targets = fetch( story )
        else
            r = fault( source )
        end
    end
    if targets then
        local show = assume[ 2 ]
        if show then
            show = mw.text.trim( show )
            if show == "" then
                show = false
            end
        end
        if show == "_" then
            show = ""
        elseif show then
            show = string.format( "[[%s|%s]]", page.prefixedText, show )
        end
        r = friends( targets, true, false, assume, active, show )
    elseif not r then
        r = fault( source or "massmessage|namespace:title" )
    end
    if assume.subst  and  not mw.isSubsting() then
        local s = string.format( "&#123;&#123;subst:%s&#125;&#125;",
                                 assume.subst )
        r = fault( s )
    end
    return r
end -- massmessage()



local function userlist( assume, active, area )
    -- Create text from template transclusion
    -- Parameter:
    --     assume  -- table with default options
    --     active  -- table with current options
    --     area    -- true: always wide area = URL
    -- Returns:
    --     string
    return friends( active, false, area, assume, active, false )
end -- userlist()



-- Export
local p = { }

function p.failsafe()
    return Serial
end

function p.massmessage( a1, a2 )
    local r
    if type( a1 ) == "table" then
        local p1, p2
        if type( a1.getParent ) == "function" then
            -- a1 is supposed to be a frame
            p1 = a1.args
            p2 = a1:getParent().args
        else
            p1 = a1
            if type( a2 ) == "table" then
                p2 = a2
            else
                p2 = { }
            end
        end
        r = massmessage( p1, p2 )
    else
        r = fault( "Pinging::massmessage()" )
    end
    return r
end

function p.maxecho()
    return tostring( MaxEcho )
end

function p.noping( frame )
    return userlist( frame.args, frame:getParent().args, true )
end

function p.ping( frame )
    return userlist( frame.args, frame:getParent().args, false )
end

return p