通过 Sulfur.wiki 可快速访问本维基!
本WIKI编辑权限开放,欢迎收藏起来防止迷路,也希望有爱的小伙伴和我们一起编辑哟~

全站通知:

模块:JSONFetcher

来自火湖WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索

此模块的文档可以在模块:JSONFetcher/doc创建

local p = {}
local json = mw.text.jsonDecode
local cache = require "mw.ext.LuaCache"

-- 获取 JSON 数据
function p.getData(frame)
    local jsonPage = '火湖:物品数据.json' -- 数据页面路径
    local cacheKey = "data_" .. jsonPage -- 第一层缓存键
    
    local cachedData = cache.get(cacheKey)
    if cachedData then
        return json(cachedData) -- 如果第一层缓存命中,直接返回解析后的数据
    end

    local content = mw.title.new(jsonPage):getContent()
    if not content then
        return "无法获取数据"
    end

    local data = json(content)
    if not data then
        return "数据格式错误"
    end

    -- 将原始 JSON 数据存入第一层缓存
    cache.set(cacheKey, content, 3600)
    return data
end

-- 获取嵌套值,支持 ! 分隔符和数组索引
function p.fetch(frame)
    -- 获取调用参数并生成缓存键
    local key = frame.args[1]
    local filters = frame.args[2] or ""
    local cacheKey = "fetch_" .. (key or "") .. "_" .. filters -- 第一层缓存键
    local secondCacheKey = cacheKey .. "_filtered" -- 第二层缓存键

    -- 检查第二层缓存
    local secondCachedResult = cache.get(secondCacheKey)
    if secondCachedResult then
        return secondCachedResult -- 如果第二层缓存命中,直接返回结果
    end

    -- 检查第一层缓存
    local cachedResult = cache.get(cacheKey)
    if cachedResult then
        return cachedResult -- 如果第一层缓存命中,直接返回结果
    end

    local data = p.getData(frame)
    if type(data) == "string" then
        return data -- 如果出错,直接返回错误信息
    end

    if not key then
        return "未指定参数"
    end

    -- 解析键,支持 ! 分隔符来进行索引
    local function getNestedValue(data, key)
        for part in key:gmatch("[^!]+") do
            part = part:match("^%s*(.-)%s*$") -- 去掉前后空格
            if type(data) == "table" then
                local index = tonumber(part)
                if index then
                    data = data[index]
                else
                    data = data[part] or data["." .. part]
                end
            else
                return nil
            end
        end
        return data
    end

    -- 检查是否需要排除或保留指定的键或值(精确匹配)
    local function matchesExact(item, pattern)
        if not pattern then return false end
        for matchPattern in pattern:gmatch("[^;]+") do
            matchPattern = matchPattern:match("^%s*(.-)%s*$") -- 去掉空格
            if tostring(item) == matchPattern then
                return true
            end
        end
        return false
    end

    -- 解析保留和排除参数
    local function parseFilterParameter(filters)
        if not filters then return nil, nil, nil, nil end
        local excludeKeyPattern, excludeValuePattern, includeKeyPattern, includeValuePattern
        for part in filters:gmatch("[^;]+") do
            part = part:match("^%s*(.-)%s*$")
            if part:sub(1, 3) == "!k:" then
                excludeKeyPattern = part:sub(4)
            elseif part:sub(1, 3) == "!v:" then
                excludeValuePattern = part:sub(4)
            elseif part:sub(1, 2) == "k:" then
                includeKeyPattern = part:sub(3)
            elseif part:sub(1, 2) == "v:" then
                includeValuePattern = part:sub(3)
            end
        end
        return excludeKeyPattern, excludeValuePattern, includeKeyPattern, includeValuePattern
    end

    -- 递归过滤嵌套数据
    local function filterNestedData(data, excludeKeyPattern, excludeValuePattern, includeKeyPattern, includeValuePattern)
        if type(data) ~= "table" then
            -- 对非表数据应用值排除和保留规则(精确匹配)
            if matchesExact(data, excludeValuePattern) then
                return nil
            end
            if includeValuePattern and not matchesExact(data, includeValuePattern) then
                return nil
            end
            return data
        end

        -- 对表数据应用键排除、键保留和递归过滤(精确匹配)
        local filteredData = {}
        for k, v in pairs(data) do
            if matchesExact(k, excludeKeyPattern) then
                -- 排除键
            elseif includeKeyPattern and not matchesExact(k, includeKeyPattern) then
                -- 不符合保留键规则
            elseif tostring(k):match("^%?_") then
                -- 排除以 ?_ 开头的键
            else
                local filteredValue = filterNestedData(v, excludeKeyPattern, excludeValuePattern, includeKeyPattern, includeValuePattern)
                if filteredValue ~= nil then
                    filteredData[k] = filteredValue
                end
            end
        end
        return filteredData
    end

    -- 获取嵌套数据
    local value = getNestedValue(data, key)
    if value == nil then
        return nil
    end

    -- 解析排除和保留规则
    local excludeKeyPattern, excludeValuePattern, includeKeyPattern, includeValuePattern = parseFilterParameter(filters)

    -- 过滤数据
    local filteredValue = filterNestedData(value, excludeKeyPattern, excludeValuePattern, includeKeyPattern, includeValuePattern)

    -- 生成返回值
    local result
    if type(filteredValue) == "table" then
        local keys = {}
        for k, _ in pairs(filteredValue) do
            table.insert(keys, k)
        end
        result = table.concat(keys, ", ")
    else
        result = tostring(filteredValue)
    end

    -- 将未过滤结果存入第一层缓存
    cache.set(cacheKey, result, 3600)

    -- 将最终过滤结果存入第二层缓存
    cache.set(secondCacheKey, result, 3600)

    return result
end

return p