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

Module:UserGroup

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

本模块为萌娘百科维护和管理人员的信息显示和列举提供支持,它主要任务有:

  1. Template:萌娘百科的苦力 中显示各个用户组的所有用户,并且计数;
  2. Module:Summon 提供获取所有可投票的维护人员的接口;
  3. 统计各用户组可投票的成员的总人数。
目前本模块基于机器人维护的半自动更新用户组列表,因此在非必要情况下不建议修改相关的代码。
local luaq = require("Module:Luaq") -- 加载查询模块。

local module = {}

local data = mw.text.jsonDecode(mw.title.new("Module:UserGroup/data"):getContent())
local config = mw.text.jsonDecode(mw.title.new("Module:UserGroup/config"):getContent())

local alias = { -- 别名,自己动手添加~
    ["staff"] = "staff",
    ["职"] = "staff",
    
    ["b"] = "bureaucrat",
    ["行政员"] = "bureaucrat",
    ["行政員"] = "bureaucrat",
    ["行政"] = "bureaucrat",
    ["行"] = "bureaucrat",
    
    ["cu"] = "checkuser",
    ["用户查核员"] = "bureaucrat",
    ["用戶查核員"] = "bureaucrat",
    ["使用者查核員"] = "bureaucrat",
    ["查核员"] = "bureaucrat",
    ["查核員"] = "bureaucrat",
    ["查核"] = "bureaucrat",
    ["查"] = "bureaucrat",
    
    ["sp"] = "suppress",
    ["监督员"] = "suppress",
    ["監督員"] = "suppress",
    ["监督"] = "suppress",
    ["監督"] = "suppress",
    ["监"] = "suppress",
    ["監"] = "suppress",
    
    ["s"] = "sysop",
    ["管理员"] = "sysop",
    ["管理員"] = "sysop",
    ["管理"] = "sysop",
    ["管"] = "sysop",
    
    ["p"] = "patroller",
    ["维护姬"] = "patroller",
    ["維護姬"] = "patroller",
    ["巡查员"] = "patroller",
    ["巡查員"] = "patroller",
    ["巡查姬"] = "patroller",
    ["巡查"] = "patroller",
    ["巡"] = "patroller",
    ["维"] = "patroller",
    ["維"] = "patroller",
    
    ["ia"] = "interface-admin",
    ["界面管理员"] = "interface-admin",
    ["介面管理員"] = "interface-admin",
    ["界管"] = "interface-admin",
    ["介管"] = "interface-admin",
    ["界"] = "interface-admin",
    ["介"] = "interface-admin",
    
    ["te"] = "techeditor",
    ["技术编辑员"] = "techeditor",
    ["技術編輯員"] = "techeditor",
    ["技编"] = "techeditor",
    ["技編"] = "techeditor",
    ["技"] = "techeditor",
    
    ["sc"] = "special-contributor",
    ["特殊贡献者"] = "special-contributor"
}
local order = { -- 同[[Help:用户标识]]顺序
    "staff",                   -- STAFF
    "bureaucrat",              -- 行政员
    "checkuser",               -- 用户核查员
    "suppress",                -- 监督员
    "sysop",                   -- 管理员
    "patroller",               -- 维护姬
    "honoredmaintainer",       -- 荣誉维护人员
    "special-contributor",      -- 特殊贡献者
    "interface-admin",         -- 界面管理员
    "templateeditor",          -- 技术编辑员
    "bot",                     -- 机器人
    "flood",                   -- 机器用户
    "ipblock-exempt",          -- IP封禁豁免者
    "goodeditor",              -- 优质编辑者
    "manually-confirmed"       -- 手动确认用户
}
function table.indexof(t, item)
    for i, v in ipairs(t) do
        if v == item then return i end
    end
    return 0
end

local getGroups = function(filter)
    return luaq.iasQuery(mw.text.split(filter, "%s+"))
            :select(function(_, name) return alias[name] or name end)
            :distinct()
            :orderBy(function(aname) return table.indexof(order, aname) end)
            :where(function(_, aname) return data[aname] ~= nil end)
            :select(function(_, aname) return data[aname] end)
            :query()
end
--[[
    供Module:Summon(大召唤术)读取数据的接口。
    filter: 空格间隔,别名见上方alias表。
--]]
function module.enumerate(filter)
    local users = {}
    local groups
    if type(filter) == "string" then
        groups = getGroups(filter)
    end
    if groups == nil or #groups == 0 then
        -- 由于行政员默认拥有管理员用户组,因此在显示时需要去重。
        local sysop = {}
        for _, user in ipairs(data.sysop or {}) do
            local flag = false
            for _, _user in ipairs(data.bureaucrat or {}) do
                if user == _user then
                    flag = true
                    break
                end
            end
            if flag == false then table.insert(sysop, user) end
        end
        groups = { data.bureaucrat or {}, sysop, data.patroller or {} } -- 默认召唤的是所有维护人员(行政员、管理员、巡查姬)。
    end
    for _, group in ipairs(groups) do
        for _, val in ipairs(group) do
            if mw.text.trim(val) ~= "" then
                local user = config[val]
                if (user == nil or user.active ~= false) then
                    table.insert(users, mw.text.trim(val))
                end
            end
        end
    end
    
    return users
end

local UserGroupInfo = function(group, frame)
    local parent = frame:getParent()
    if parent and parent:getTitle() == "Template:UserGroup" then
        frame = parent
    end
    if frame.args["Count"] then
        return #group
    else
        local list = {}
        for key, val in ipairs(group) do
            if mw.text.trim(val) ~= "" then
                local user = config[val]
                if (user) then
                    table.insert(list,
                        frame:preprocess(user.prefix or "")..
                        frame:expandTemplate{ title = "User", args = { val } }..
                        frame:preprocess(user.postfix or "")
                    )
                else
                    table.insert(list, frame:expandTemplate{ title = "User", args = { val } })
                end
            end
        end
        return table.concat(list, " • ")
    end
end

--[==[
动态生成用以展示某一用户组成员列表的模块导出函数,
生成操作支持的用户组同[[Module:UserGroup/data]]中明确列举出的用户组,没有列举出的将不会支持。
在调用模块时,仍然可以使用{{#invoke|UserGroup|【用户组的代号】}},旧代码可不做修改。
  ]==]
for gname, g in pairs(data) do
    module[gname] = function(frame)
        return UserGroupInfo(g, frame)
    end
end
--[[
由于行政员默认拥有管理员用户组,因此在显示时需要去重。
  ]]
module.sysop = function(frame)
    local bureaucrat = data.bureaucrat or {}
    local sysop = luaq.iasQuery(data.sysop or {})
        :where(function(_, user) return table.indexof(bureaucrat, user) < 1 end)
        :query()
    return UserGroupInfo(sysop, frame)
end

function module.vote_count(frame)
    local filter = mw.text.trim(frame.args[1] or "")
    local adjust = tonumber(frame.args[2]) or 0
    local check_vote = function(_, users)
        local retn = 0
        for _, val in ipairs(users) do
            if mw.text.trim(val) ~= "" then
                local user = config[val]
                retn = retn + ((user == nil or user.vote ~= false) and 1 or 0)
            end
        end
        return retn
    end
    
    local groups = getGroups(filter) -- 获取要求和的用户组列表
    if groups == nil or #groups == 0 then return 0 end
    return adjust + luaq.iasQuery(groups)
        :select(check_vote)
        :sum(function(x, y) return { x[1] + y[1] } end) -- 求和
end

return module