跳转到内容

模組:沙盒/PexEric/1

维基百科,自由的百科全书

这是本页的一个历史版本,由PexEric留言 | 贡献2025年5月31日 (六) 19:10编辑。这可能和当前版本存在着巨大的差异。

local p = {}

-- Dependency modules
local TPV -- Lazily loaded: require('Module:Template parameter value')
local Args -- Lazily loaded: require('Module:Arguments')
local PatternedCandidateUtils -- Not required as a module, invoked via parser function

-- Configuration for different content review types
-- These settings are derived from your examples.
local candidateConfigs = {
    DYKC = {
        pageTitle = "Wikipedia:新条目推荐/候选",
        pattern = "%{{!}}%s*article%s*=%s*(.-)%s*[%}%{{!}}]",
        linkprefix = "Wikipedia:新条目推荐/候选#",
        -- No black or blackregex specified in example, can be added if needed
    },
    PR = {
        pageTitle = "Wikipedia:同行评审/提案区",
        pattern = "====%s*(.-)%s*===",
        linkprefix = "Wikipedia:同行评审#",
        postProcessInvoke = { -- For #invoke:String|replace
            module = "String",
            func = "replace",
            args = { -- source is added dynamically
                pattern = "-%[%[:Wikipedia:同行评审#=+.-{{!}}=+.-%]%]",
                plain = "false"
            }
        }
    },
    GAC = {
        pageTitle = "Wikipedia:優良條目評選/提名區",
        pattern = "====%s*(.-)%s*===%f[^=]",
        blackregex = "==%s*(.-)%s*=",
        linkprefix = "Wikipedia:優良條目評選#"
    },
    FAC = {
        pageTitle = "Wikipedia:典范条目评选/提名区",
        pattern = "====%s*(.-)%s*===%f[^=]",
        blackregex = "==%s*(.-)%s*=",
        linkprefix = "Wikipedia:典范条目评选#",
        postProcessInvoke = {
            module = "String",
            func = "replace",
            args = {
                pattern = "-%[%[:Wikipedia:典范条目评选#=+.-{{!}}=+.-%]%]",
                plain = "false"
            }
        }
    },
    FLC = {
        pageTitle = "Wikipedia:特色列表评选/提名区",
        pattern = "====%s*(.-)%s*===%f[^=]",
        blackregex = "==%s*(.-)%s*=",
        linkprefix = "Wikipedia:特色列表评选#"
    },
    ITNC = {
        pageTitle = "Wikipedia:新闻动态候选",
        pattern = "%{{!}}%s*article%s*=%s*(.-)%s%{{!}}",
        linkprefix = "Wikipedia:新闻动态候选#"
    }
}

-- WikiProject Banner Shell and its redirects (as Lua patterns)
-- These need to be Lua patterns compatible with string.match and TPV's treat_as_regex
local wpbs_redirect_patterns = {
	"wiki%s*project%s*banner%s*shell", 
	"w?pj?%s*banner%s*shell", 
	"wiki%s*project%s*banners", 
	"multiple%s*wikiprojects?", 
	"wiki%s*project%s*shell",
	"pjbs",
	"[維维]基[专專][题題][橫横]幅", 
	"多?[個个]?[維维]?基?[专專][题題][橫横]幅",
	"[維维]基[专專][题題]", 
	"多?[個个]?[維维]?基?[专專][题題]",
	"[专專][题題][橫横]幅", 
	"通用[評评][級级]",
}

-- Helper function to get candidate titles from a review page
-- reviewType: string key from candidateConfigs (e.g., "DYKC")
-- frame: the current Scribunto frame
local function getCandidatePageTitles(reviewType, frame)
    local config = candidateConfigs[reviewType]
    if not config then
        return {}, "未知的内容评选类型: " .. tostring(reviewType)
    end

    local pcu_args = {
        title = config.pageTitle,
        pattern = config.pattern
        -- linkprefix is handled by PCU, we extract titles from its output
    }
    if config.linkprefix then pcu_args.linkprefix = config.linkprefix end
    if config.black then pcu_args.black = config.black end
    if config.blackregex then pcu_args.blackregex = config.blackregex end

    -- Build arguments for #invoke:PatternedCandidateUtils|list
    local invoke_pcu_table_args = {'PatternedCandidateUtils', 'list'}
    for k, v in pairs(pcu_args) do
        table.insert(invoke_pcu_table_args, k .. '=' .. v)
    end

    local raw_output = frame:callParserFunction{
        name = '#invoke',
        args = invoke_pcu_table_args
    }

    -- Apply post-processing if configured (e.g., for PR, FAC)
    if config.postProcessInvoke then
        local string_replace_args = {
            config.postProcessInvoke.module,
            config.postProcessInvoke.func,
            source = raw_output
        }
        for k, v in pairs(config.postProcessInvoke.args) do
            table.insert(string_replace_args, k .. '=' .. v)
        end
        raw_output = frame:callParserFunction{
            name = '#invoke',
            args = string_replace_args
        }
    end

    if raw_output == '暂无' or raw_output == '' then
        return {}
    end

    local titles = {}
    -- PatternedCandidateUtils|list outputs links like [[Prefix#Page Title|Page Title]]
    -- We need to extract the "Page Title" part.
    -- The gmatch pattern captures the text *after* the pipe if a pipe exists,
    -- or the whole link target if no pipe (though PCU usually adds a pipe).
    -- This regex assumes the link format from PCU.
    -- The display text (second part of [[L|D]]) is what we want.
    for display_text in mw.ustring.gmatch(raw_output, "%[%[[^%]|]+%|(.-)%]%]") do
        table.insert(titles, display_text)
    end
    
    -- Fallback if the above gmatch fails (e.g. if PCU changes its output format slightly
    -- or if there are links without pipes, though less likely for PCU list output)
    if #titles == 0 and raw_output ~= '暂无' and raw_output ~= '' then
         -- This alternative tries to get the article title from the link target directly if linkprefix was used
        local linkPrefixPattern = config.linkprefix and mw.ustring.gsub(config.linkprefix, "[%(%)%.%+%-%*%?%[%]%^%$%%]", "%%%0") or ""
        if linkPrefixPattern ~= "" then
             for article_part in mw.ustring.gmatch(raw_output, "%[%[" .. linkPrefixPattern .. "([^%]|]+)") do
                table.insert(titles, mw.ustring.gsub(article_part, "_", " "))
            end
        end
        -- If still no titles, it might be a simpler list, try a broader match
        if #titles == 0 then
             for display_text in mw.ustring.gmatch(raw_output, "%[%[%s*(.-)%s*%]%]") do
                local clean_title = mw.ustring.match(display_text, "^[^|]+$") or mw.ustring.match(display_text, ".-|(.*)")
                if clean_title then
                	table.insert(titles, clean_title)
                end
            end
        end
    end

    return titles
end

-- Helper function to get WikiProject names from an article's talk page
-- articleTitle: string, the title of the article (not the talk page)
local function getProjectsForArticle(articleTitle)
    if not TPV then TPV = require('Module:Template parameter value') end

    local talkPageTitleObj = mw.title.new(articleTitle, 'Talk')
    if not talkPageTitleObj or not talkPageTitleObj.exists then
        return {} -- Talk page doesn't exist
    end
    local talkPageTitle = talkPageTitleObj.prefixedText

    -- Try to get the content of the first unnamed parameter of WikiProject banner shell (or its redirects)
    local success, param1_content = TPV.getParameter(
        talkPageTitle,
        wpbs_redirect_patterns, -- Table of regex patterns for template names
        "1",                    -- Parameter name "1"
        { treat_as_regex = true } -- Tell TPV that `wpbs_redirect_patterns` contains regexes
    )

    if not success or not param1_content or param1_content == "" then
        return {} -- Template not found, or parameter 1 is empty
    end

    local projects = {}
    -- Extract template names from the parameter content
    -- Matches {{Template Name ...}} or {{Template Name}}
    -- Captures "Template Name"
    for tmpl_name in mw.ustring.gmatch(param1_content, "{{%s*([^}|%s][^}|]*)") do
        -- Trim whitespace just in case, though the pattern is quite specific
        local cleaned_name = mw.text.trim(tmpl_name)
        if cleaned_name ~= "" then
            table.insert(projects, cleaned_name)
        end
    end
    return projects
end

--[[
Function 1: listProjects
Lists all candidate items for a specific content review and their associated WikiProjects in a table.
Parameters from frame:
  args[1] or args.type: The type of content review (e.g., "DYKC", "GAC"). Required.
  args.prefix: Wikitext to prepend to each article name. Default: "".
  args.suffix: Wikitext to append to each article name. Default: "".
  args.tpl_prefix: Wikitext to prepend to each project template name. Default: "{{tl|".
  args.tpl_suffix: Wikitext to append to each project template name. Default: "}}".
--]]
function p.listProjects(frame)
    local args = frame.args
    local reviewType = args[1] or args.type
    if not reviewType then
        return "<span class=\"error\">错误:未指定内容评选类型 (例如 DYKC, GAC)。</span>"
    end

    local article_prefix = args.prefix or ""
    local article_suffix = args.suffix or ""
    local tpl_prefix = args.tpl_prefix -- No default here, will check nil later
    local tpl_suffix = args.tpl_suffix -- No default here

    -- Set default template wrappers if not provided or empty
    if tpl_prefix == nil or tpl_prefix == "" then tpl_prefix = "{{tl|" end
    if tpl_suffix == nil or tpl_suffix == "" then tpl_suffix = "}}" end


    local candidateTitles, err = getCandidatePageTitles(reviewType, frame)
    if err then return "<span class=\"error\">获取候选项目失败:" .. err .. "</span>" end

    if #candidateTitles == 0 then
        return "指定的评选栏目下目前没有候选项目。"
    end

    local output = {}
    table.insert(output, '{| class="wikitable sortable"')
    table.insert(output, '! 条目 !! 所属专题')

    for _, title in ipairs(candidateTitles) do
        local projects = getProjectsForArticle(title)
        local formattedProjects = {}
        if #projects > 0 then
            for _, projName in ipairs(projects) do
                table.insert(formattedProjects, tpl_prefix .. projName .. tpl_suffix)
            end
            table.insert(output, "|-\n| " .. article_prefix .. title .. article_suffix ..
                                 " || " .. table.concat(formattedProjects, "、"))
        else
            table.insert(output, "|-\n| " .. article_prefix .. title .. article_suffix ..
                                 " || ''暂无专题或未能获取''")
        end
    end

    table.insert(output, "|}")
    return table.concat(output, "\n")
end

--[[
Function 2: listCandidatesByProject
Lists candidate items from a specific content review that belong to one or more given WikiProjects.
Parameters from frame:
  args[1] or args.type: The type of content review (e.g., "DYKC", "GAC"). Required.
  args.prefix: Wikitext to prepend to each article name. Default: "".
  args.suffix: Wikitext to append to each article name. Default: "".
  args.project1, args.project2, ...: Regex patterns for WikiProject names. At least one is required.
--]]
function p.listCandidatesByProject(frame)
    if not Args then Args = require('Module:Arguments') end
    local allArgs = Args.getArgs(frame) -- Use Module:Arguments for easier access to projectN

    local reviewType = allArgs[1] or allArgs.type
    if not reviewType then
        return "<span class=\"error\">错误:未指定内容评选类型 (例如 DYKC, GAC)。</span>"
    end

    local article_prefix = allArgs.prefix or ""
    local article_suffix = allArgs.suffix or ""

    local project_patterns = {}
    local i = 1
    while true do
        local proj_pattern = allArgs['project' .. i]
        if proj_pattern then
            table.insert(project_patterns, proj_pattern)
        else
            break
        end
        i = i + 1
    end

    if #project_patterns == 0 then
        return "<span class=\"error\">错误:至少需要指定一个专题匹配模式 (project1, project2, ...)。</span>"
    end

    local candidateTitles, err = getCandidatePageTitles(reviewType, frame)
    if err then return "<span class=\"error\">获取候选项目失败:" .. err .. "</span>" end
    
    if #candidateTitles == 0 then
        return "指定的评选栏目下目前没有候选项目。"
    end

    local matched_candidates_output = {}
    for _, title in ipairs(candidateTitles) do
        local articleProjects = getProjectsForArticle(title)
        local match_found = false
        if #articleProjects > 0 then
            for _, projName in ipairs(articleProjects) do
                for _, pattern in ipairs(project_patterns) do
                    if mw.ustring.match(projName, pattern) then
                        match_found = true
                        break -- Found a match for this article, no need to check other patterns for this project
                    end
                end
                if match_found then
                    break -- No need to check other projects for this article
                end
            end
        end

        if match_found then
            table.insert(matched_candidates_output, article_prefix .. title .. article_suffix)
        end
    end

    if #matched_candidates_output == 0 then
        return "没有找到符合指定专题条件的候选项目。"
    else
        return "# " .. table.concat(matched_candidates_output, "\n# ")
    end
end

return p