跳转到内容

模組:Update monitor

本页使用了标题或全文手工转换
维基百科,自由的百科全书

local p = {}

function p.main(frame)
    -- 獲取來自外部調用模板的所有參數
    local args = frame:getParent().args
	-- 命名空間與頁面型態解析函數
    local function get_type_text(ns, title_str)
        local clean_title = mw.text.trim(title_str or "")
        
        -- 判定特定字首的偽命名空間
        if string.match(clean_title, "^[Mm][Oo][Ss]:") then
            return '-{zh-hans:格式手册;zh-hant:格式手冊;}-'
        elseif string.match(clean_title, "^[Ll][Tt][Aa]:") then
            return '-{zh-hans:LTA页面;zh-hant:LTA頁面;}-'
            
        -- 判定其他常見的偽命名空間字首
        elseif string.match(clean_title, "^[Ww][Pp]:") or
               string.match(clean_title, "^[Cc][Aa][Tt]:") or
               string.match(clean_title, "^[Tt]:") or
               string.match(clean_title, "^[Hh]:") or
               string.match(clean_title, "^[Pp]:") or
               string.match(clean_title, "^[Dd]:") or
               string.match(clean_title, "^[Mm]:") or
               string.match(clean_title, "^[Ii]:") or
               string.match(clean_title, "^[Nn]:") or
               string.match(clean_title, "^[Rr]:") then
            return '-{zh-hans:伪命名页面;zh-hant:偽命名頁面;}-'
            
        -- 判定討論命名空間(所有奇數ID)
        elseif ns % 2 == 1 then
            return '-{zh-hans:讨论页;zh-hant:討論頁;}-'
            
        -- 標準命名空間
        elseif ns == 0 then
            return '條目'
        elseif ns == 2 then
            return '-{zh-hans:用户页;zh-hk:用戶頁;zh-tw:使用者頁面}-'
        elseif ns == 4 then
            return '-{zh-hans:页面;zh-hant:頁面;}-'
        elseif ns == 6 then
            return '-{zh-hans:文件;zh-hant:檔案;}-'
        elseif ns == 8 then
            return '頁面'
        elseif ns == 10 then
            return '模板'
        elseif ns == 12 then
            return '-{zh-hans:帮助页面;zh-hant:說明頁面;}-'
        elseif ns == 14 then
            return '分類'
        elseif ns == 100 then
            return '主題'
        elseif ns == 102 then
            return '-{zh-hans:维基专题;zh-hant:維基專題;}-'
        elseif ns == 118 then
            return '草稿'
        elseif ns == 828 then
            return '-{zh-hans:模块;zh-hant:模組;}-'
        end

        return '頁面'
    end
    local currentTitle = mw.title.getCurrentTitle()
    
    -- 載入yesno模組以處理small參數
    local yesno = require('Module:Yesno')
    local is_small = yesno(args.small) or false

    -- 決定目標頁面名稱並判斷是否為跨頁面目標
    local target_name = args.target or args[1]
    local is_remote = true
    if not target_name or mw.text.trim(target_name) == '' then
        target_name = currentTitle.fullText
        is_remote = false
    else
        target_name = mw.text.trim(target_name)
    end

    local timestamp_str
    -- demo參數
    if args.demo and mw.text.trim(args.demo) ~= '' then
        timestamp_str = frame:callParserFunction('#time', { 'YmdHis', 'now - ' .. mw.text.trim(args.demo) })
    else
        timestamp_str = frame:expandTemplate{ title = 'REVISIONTIMESTAMP', args = { target_name } }
        -- 若抓取失敗則退回當前頁面時間
        if not timestamp_str or mw.text.trim(timestamp_str) == '' or string.match(timestamp_str, "錯誤") then
            timestamp_str = frame:expandTemplate{ title = 'REVISIONTIMESTAMP', args = { currentTitle.fullText } }
        end
    end

    -- 轉換為Unix時間戳記以利後續的過期邏輯數學計算
    local current_ts = tonumber(frame:callParserFunction('#time', { 'U' }))

    -- 將30 min、1 hour等轉換為過期時間戳記(未填寫則永久藍色)
    local function get_expiry(val)
        if not val or mw.text.trim(val) == '' then
            return 9999999999
        end
        local clean_val = string.lower(mw.text.trim(val))
        if clean_val == 'disable' or clean_val == 'none' then
            return 9999999999
        end

        local success, result = pcall(function()
            return tonumber(frame:callParserFunction('#time', { 'U', timestamp_str .. ' + ' .. val }))
        end)

        return success and result or 9999999999
    end

    local red_expiry = get_expiry(args.red)
    local yellow_expiry = get_expiry(args.yellow)
    local green_expiry = get_expiry(args.green)

    -- 狀態判定
    local state = 'blue'
    if current_ts >= red_expiry then
        state = 'red'
    elseif current_ts >= yellow_expiry then
        state = 'yellow'
    elseif current_ts >= green_expiry then
        state = 'green'
    end

    -- 定義CSS與對應圖標
    local styles = {
        blue = 'background-color:var(--background-color-progressive-subtle, #F5FAFF); border: 2px solid var(--border-color-progressive, #36C); color: inherit;',
        green = 'background-color:var(--background-color-success-subtle,#DFFFDF); border: 2px solid var(--border-color-success,#008000); color: inherit;',
        yellow = 'background-color:var(--background-color-warning-subtle,#FDF1D1); border: 2px solid var(--border-color-warning,orange); color: inherit;',
        red = 'background-color:var(--background-color-error-subtle,#FDD); border: 2px solid var(--border-color-error,#DE0000); color: inherit;'
    }

    local icon_size = is_small and '25px' or '40px'
    local images = {
        blue = '[[File:State best.svg|' .. icon_size .. '|alt=資訊]]',
        green = '[[File:State good.svg|' .. icon_size .. '|alt=已確認]]',
        yellow = '[[File:State notice.svg|' .. icon_size .. '|alt=注意]]',
        red = '[[File:State warning.svg|' .. icon_size .. '|alt=警告]]'
    }

    -- 名詞主體與連結生成
    local subject_text
    if is_remote then
        if string.match(target_name, ":") or mw.title.new(target_name) then
            local targetTitle = mw.title.new(target_name) or currentTitle
            local ns = targetTitle.namespace
            local type_text = get_type_text(ns, target_name)

            local display_link
            local use_tl = yesno(args.tl)
            if use_tl then
                if targetTitle.namespace == 10 then
                    display_link = '{{[[Template:' .. targetTitle.text .. '|' .. targetTitle.text .. ']]}}'
                else
                    display_link = '{{[[' .. targetTitle.prefixedText .. '|' .. targetTitle.text .. ']]}}'
                end
            else
                display_link = '[[' .. target_name .. ']]'
            end

            if args.this == 'yes' then
                subject_text = '此' .. display_link .. type_text
            else
                subject_text = display_link .. type_text
            end
        else
            local prefix = (args.this == 'yes') and '此' or '本'
            subject_text = prefix .. target_name
        end
    else
		local ns = currentTitle.namespace
        local type_text = get_type_text(ns, currentTitle.fullText)
        local prefix = (args.this == 'yes') and '此' or '本'
        subject_text = prefix .. type_text
    end

    -- 小字說明
    local function get_note_text(val)
        if not val or mw.text.trim(val) == '' then return nil end
        local clean = string.lower(mw.text.trim(val))
        if clean == 'disable' or clean == 'none' then return nil end

        local out = val
        out = string.gsub(out, "[Mm][Ii][Nn][Uu][Tt][Ee][Ss]?", "分鐘")
        out = string.gsub(out, "[Mm][Ii][Nn]", "分鐘")
        out = string.gsub(out, "[Hh][Oo][Uu][Rr][Ss]?", "小時")
        out = string.gsub(out, "[Dd][Aa][Yy][Ss]?", "天")
        out = string.gsub(out, "[Ww][Ee][Ee][Kk][Ss]?", "週")
        out = string.gsub(out, "[Mm][Oo][Nn][Tt][Hh][Ss]?", "個月")
        out = string.gsub(out, "[Yy][Ee][Aa][Rr][Ss]?", "年")
        out = string.gsub(out, "[Ss][Ee][Cc][Oo][Nn][Dd][Ss]?", "秒")
        out = string.gsub(out, "[Ss][Ee][Cc]", "秒")
        return out
    end

    local yellow_note = get_note_text(args.yellow)
    local red_note = get_note_text(args.red)
    local green_note = get_note_text(args.green)

    local small_note = ""
    if not green_note and not yellow_note and not red_note then
        small_note = "除非設定時間,否則本框恆為藍色。"
    else
        if green_note then
            small_note = small_note .. "更新後本框顯示為藍色;超過" .. green_note .. "本框會變成綠色"
        else
            small_note = small_note .. "更新後本框顯示為藍色"
        end

        if yellow_note then
            small_note = small_note .. ";超過" .. yellow_note .. "本框會變成黃色"
        end

        if red_note then
            small_note = small_note .. ";超過" .. red_note .. "本框則會變成紅色"
        end

        small_note = small_note .. "。"
        -- 自動修正句尾的分號為句號
        if string.sub(small_note, -3) == ";" then
            small_note = string.sub(small_note, 1, -4) .. "。"
        end
    end

    -- 組裝文字與動態模板解析
    local main_text = subject_text .. "最後於'''{{Time ago|" .. timestamp_str .. "}}'''編輯"
    if args.tittle and mw.text.trim(args.tittle) ~= '' then
        main_text = main_text .. "," .. mw.text.trim(args.tittle)
    end
    main_text = main_text .. "。({{purge|更新-{zh-hans:缓存;zh-hant:快取;}-}})"

    local final_note = small_note
    if args.text and mw.text.trim(args.text) ~= '' then
        final_note = mw.text.trim(args.text)
    end

    local text_content
    if is_small then
        -- small模式:上次編輯間距
        text_content = main_text
    else
        -- 一般模式:上次編輯間距+變色說明
        text_content = main_text .. "<br>" .. "<small>" .. final_note .. "</small>"
    end

    local parsed_text = frame:preprocess(text_content)

    -- 0分鐘前或-1分鐘前為剛剛更新---small+一般
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''0秒前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''1秒前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''2秒前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''3秒前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''4秒前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''5秒前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''6秒前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''7秒前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''8秒前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''9秒前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''10秒前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''0分鐘前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''0分钟前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''%-1分鐘前'''編輯。", "'''剛剛更新'''。")
    parsed_text = mw.ustring.gsub(parsed_text, "最後於'''%-1分钟前'''編輯。", "'''剛剛更新'''。")

    -- 輸出
    local output = frame:expandTemplate{ title = 'ombox', args = {
        style = styles[state],
        image = images[state],
        text = parsed_text,
        small = is_small and 'yes' or nil
    }}

    local ns = currentTitle.namespace
    -- 主要、專案、模板、分類、主題空間才分類
    local is_valid_ns = (ns == 0 or ns == 4 or ns == 10 or ns == 14 or ns == 100)

    if is_valid_ns then
        -- badcat, badcategory:yellow或red分類
        local badcat_name = args.badcat or args.badcategory
        if badcat_name and mw.text.trim(badcat_name) ~= '' then
            if state == 'yellow' or state == 'red' then
                output = output .. '[[Category:' .. mw.text.trim(badcat_name) .. ']]'
            end
        end

        -- cat, category:全部分類
        local cat_name = args.cat or args.category
        if cat_name and mw.text.trim(cat_name) ~= '' then
            output = output .. '[[Category:' .. mw.text.trim(cat_name) .. ']]'
        end
    end

    return output
end

return p