2023年政策修订增补工作正在进行中,欢迎参与!
  • Moegirl.ICU:萌娘百科流亡社群 581077156(QQ),欢迎对萌娘百科运营感到失望的编辑者加入
  • Moegirl.ICU:账号认领正在试运行,有意者请参照账号认领流程

Module:Sandbox/滝沢朔太郎/SummonSysop

萌娘百科,万物皆可萌的百科全书!转载请标注来源页面的网页链接,并声明引自萌娘百科。内容不可商用。
跳转到导航 跳转到搜索
Template-info.svg 模块文档  [创建] [刷新]
local module = {}

local getArgs = require('Module:Arguments').getArgs
local getCode = require('Module:GetPageCode')
local wrappers = {
    'Template:沙盒',
    'Template:沙盒/群组'
}

-- 可匹配多个正则。
mw.ustring.gsub_m = function(s, patterns, repl, n)
    local length = mw.ustring.len(s)
    local init = 1
    local v1, v2
    local i = 0
    local ss = {}
    while (n == nil or i < n) and init < length do
        v1, v2 = length + 1, length
        local p = nil
        for _, pattern in ipairs(patterns) do
            local v3, v4 = mw.ustring.find(s, pattern, init, false)
            if v3 ~= nil and (v3 < v1 or (v3 == v1 and v4 <= v2)) then
                v1, v2 = v3, v4 -- 更新匹配范围。
                p = pattern -- 更新使用的正则。
            end
        end
        if p ~= nil then
            table.insert(ss, mw.ustring.sub(s, init, v1 - 1))
            local new_s = mw.ustring.gsub(mw.ustring.sub(s, v1, v2), p, repl, 1) -- 调用原生替换函数。
            table.insert(ss, new_s)
        else break
        end
        init = v2 + 1
        i = i + 1
    end
    table.insert(ss, mw.ustring.sub(s, init))
    
    return table.concat(ss)
end
-- 一个值是否在表里。
table.has = function(table, value)
    for _, item in ipairs(table) do
        if value == item then return true end    
    end
end

function module._main(args, frame)
    local users = nil
    
    local group = frame.args['group'] or frame.args['群组'] or frame.args['群組'] or ''
    local page = mw.title.new(group) or mw.title.new('Module:Sandbox/滝沢朔太郎/UserGroupSysop') -- 过滤掉含有不能使用字符的标题。
    if page.exists then
        if page.contentModel == "Scribunto" then -- 页面存在且页面内容模型为Lua源码,尝试获取枚举接口。
            local success = nil
            success, users = pcall(function(p)
                local _mod = require(tostring(p))
                if type(_mod.enumerate) == 'function' then -- 接口正确。
                    local _list = _mod.enumerate()
                    if type(_list) == 'table' then -- 接口返回值正确。
                        return _list
                    end
                end
                return nil -- 接口错误,或接口返回值错误。
            end, page)
            if not success then users = nil end -- 通过接口获取返回值过程中发生错误而失败。
        end
        page = tostring(page)
    else
        page = tostring(mw.title.makeTitle('Template', tostring(page))) -- 页面不存在默认添加Template名字空间。
    end
    
    if users == nil then -- 若已通过接口获取过Module页面提供的用户列表,则不对其代码进行识别。
        users = {}
        
        local code = getCode(page)
        -- 构造正则列表。
        local patterns = {
            '{{%s*[Uu]ser%s*|([^|}/\\]+)}}', -- 匹配{{User|XXX}}模板。
            '{{%s*[Uu]ser%s*|([^|}/\\]+)|.-}}', -- 匹配{{User|XXX|YYYY}}模板。
            '%[%[%s*[Uu][Ss][Ee][Rr]%s*:([^|%]/\\]+)%]%]', -- 匹配[[User:XXX]]。
            '%[%[%s*[Uu][Ss][Ee][Rr]%s*:([^|%]/\\]+)|.-%]%]', -- 匹配[[User:XXX|YYYY]]。
        }
        for _, alias in ipairs(mw.site.namespaces['User'].aliases) do
            -- 将别名中所有西文字母替换为正则表达式“[【大写】【小写】]"。
            alias = mw.ustring.gsub(alias, '[A-Za-z]', function(letter)
                return '[' .. mw.ustring.upper(letter) .. mw.ustring.lower(letter) .. ']'
            end)
            table.insert(patterns, '%[%[%s*' .. alias .. '%s*:([^|%]/\\]+)%]%]') -- 匹配[[【User名字空间的别名】:XXX]]。
            table.insert(patterns, '%[%[%s*' .. alias .. '%s*:([^|%]/\\]+)|.-%]%]') -- 匹配[[【User名字空间的别名】:XXX|YYYY]]。
        end
        mw.ustring.gsub_m(code, patterns, function(name)
            name = tostring(mw.title.new(name) or name) -- 标准化。
            if users[name] == nil then
                users[name] = true -- 标志已存在这个用户名。
                users[#users + 1] = name
            end
        end)
    end
    
    local except = args[1] or args['except'] or args['除去'] or ''
    for name in mw.text.gsplit(except, ',') do
        name = tostring(mw.title.new(name) or name) -- 标准化。
        users[name] = false -- 标志除去这个用户名。
    end
    
    for i = #users, 1, -1 do
        if users[users[i]] == false then
            table.remove(users, i)
        end
    end
    
    -- 由于表中无用的标志会被expandTemplate识别为调用参数,因此需要清除,保留键为正整数的键值对。
    for k, _ in pairs(users) do
        if type(k) ~= "number" then users[k] = nil end
    end
    
    return frame:expandTemplate{ title = 'Reply to', args = users }
end

function module.main(frame)
    local args = getArgs(frame, {
        trim = true,
        removeBlanks = false,
        valueFunc = function(key, value)
            if value == '' then
                return nil
            else
                return value
            end
        end,
        wrappers = wrappers
    })
    
    if not mw.isSubsting() and (os.time() >= os.time({ year = 2020, month = 7, day = 22, hour = 16, minute = 0, second = 0 })) then
        local title = frame:getTitle()
        local caller = '调用模块[['..title..'|'..mw.title.new(title).text..']]'
        local parent = frame:getParent()
        if parent then
            title = parent:getTitle()
            if table.has(wrappers, title) then
                caller = '使用'..frame:expandTemplate{ title = 'Tl', args = { mw.title.new(title).text } }
            end
        end
        local time = frame:callParserFunction{ name = '#time', args = { 'Y年n月j日(D)H:i:s', '2020-7-23' } }
        return require('Module:Error').error({ '自'..time..'(CST)起,'..caller..'时必须被[[Help:替换引用|替换引用]]。[[Category:有脚本错误的页面]]' })
    else
        return module._main(args, frame)
    end
end

return module