Modul:Pinging

Vorlagenprogrammierung Diskussionen Lua Test Unterseiten
Modul Deutsch English

Modul: Dokumentation

Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus

Dies ist die (produktive) Mutterversion eines global benutzten Lua-Moduls.
Wenn die serial-Information nicht übereinstimmt, müsste eine Kopie hiervon in das lokale Wiki geschrieben werden.
Versionsbezeichnung auf WikiData: 2022-11-14

local Pinging = { suite   = "Pinging",
                  serial  = "2022-11-14",
                  item    = 108829575,
                  maxEcho = 50,    -- currently permitted number of recipients
                  maxName = 99,    -- length of a user name
                  start   = "@",
                  suffix  = ":" }
--[==[
Support templates for pings and user lists
]==]
local Failsafe = Pinging



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
    local e = mw.html.create( "span" )
                     :addClass( "error" )
                     :css( "white-space", "nowrap" )
                     :wikitext( alert )
    return tostring( e )
end -- fault()



local function fetch( analyse, alt )
    -- Retrieve target table
    -- Parameter:
    --     analyse  -- string with page content
    --     alt      -- string with additional nick pattern, or not
    -- Returns:
    --     sequence of targets, might be 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
    if alt then
        local n, sn, sns, st, sub, tns
        i    = 1
        loop = true
        while ( loop ) do
            j, i = mw.ustring.find( s, alt, i )
            if j then
                loop   = true
                sub    = mw.ustring.sub( s, j, i )
                st, sn = mw.ustring.match( sub, alt )
                if st then
                    st = mw.text.trim( st )
                    if st == "" then
                        st = false
                    end
                end
                if st then
                    n = 2
                    if sn then
                        sn = mw.text.trim( sn )
                        if sn == "-" then
                            n = false
                        elseif sn ~= "" then
                            sns = sn:match( "^(%d+)$" )
                            if sns then
                                n = tonumber( sns )
                            else
                                tns = mw.site.namespaces[ sns ]
                                if tns then
                                    n = tns.id
                                end
                            end
                        end
                    end
                    if n then
                        st = string.format( "%s:%s",
                                            mw.site.namespaces[ n ].name,
                                            st )
                    end
                    table.insert( r, st )
                end
            else
                loop = false
            end
        end -- while loop
    end
    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 ) >  Pinging.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
                local e = mw.html.create( "span" )
                                 :css( "white-space", "nowrap" )
                                 :wikitext( show )
                show = tostring( e )
            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
                local e = mw.html.create( "span" )
                                 :addClass( "plainlinks" )
                                 :wikitext( r )
                r = tostring( e )
            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    = Pinging.maxEcho
    local n      = 0
    local lapsus, light, lost, r, s, stick
    if alter then
        stick = " "
    elseif active[ "/" ] then
        stick = active[ "/" ]
    elseif assume[ "/" ] then
        stick = assume[ "/" ]
    else
        if Pinging.stick then
            stick = Pinging.stick
        else
            local ltr = not mw.language.getContentLanguage():isRTL()
            local e   = mw.html.create( "span" )
                               :wikitext( "&#124;" )
            local s
            if ltr then
                s = "left"
            else
                s = "right"
            end
            e:css( "margin-" .. s,  "0.5em" )
            stick = tostring( e ) .. " "
            Pinging.stick = stick
        end
    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"
                        local tell   = mw.message.new( scream )
                        if tell:exists() then
                            scream = tell:numParams( max ):plain()
                        else
                            scream = string.format( "count %d &gt; %d",
                                                    n, max )
                        end
                        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  = Pinging.start
        local suffix = Pinging.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
            local e = mw.html.create( "span" )
                             :css( "display", "none" )
                             :wikitext( r )
            r = tostring( e ) .. 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 specification
    --                [ 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, assume.pattern )
        else
            r = fault( source )
        end
    end
    if targets then
        --  if   =0
        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()



Pinging.f = function ( assigned, area, assume, active )
    -- Make list of entries
    -- Parameter:
    --     assigned  -- table with pages or users
    --     area      -- true: always wide area = URL
    --     assume    -- table with default options
    --     active    -- table with current options
    -- Returns:
    --     string
    local defaults = assume  or  { }
    local current  = active  or  { }
    local r
    if type( assigned ) == "table"  and
       type( defaults ) == "table"  and
       type( current ) == "table" then
        r = friends( assigned, false, area, defaults, current, false )
    else
        local s
        if type( assigned ) ~= "table" then
            s = "assigned"
        end
        if type( defaults ) ~= "table" then
            if s then
                s = s .. ", assume"
            else
                s = "assume"
            end
        end
        if type( current ) ~= "table" then
            if s then
                s = s .. ", active"
            else
                s = "active"
            end
        end
        s = s .. " not 'table'"
        r = fault( s )
    end
    return r
end -- Pinging.f()



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
    -- 2020-08-17
    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
        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 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( Pinging.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

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

Content Disclaimer

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.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.