Module:RecursiveSelectiveList: Difference between revisions

From Ikwipedia
No edit summary
No edit summary
 
(49 intermediate revisions by the same user not shown)
Line 1: Line 1:
local function fetchCategoryMembers(categoryName, cmtype, continue)
local p = {}
    local url = mw.uri.fullUrl('api.php', {
        action = 'query',
        list = 'categorymembers',
        cmtitle = 'Category:' .. categoryName,
        cmtype = cmtype,
        cmlimit = 'max',
        format = 'json',
        cmcontinue = continue
    })


     local response = mw.http.get(url)
-- Helper function to format numbers with commas
     if response.status ~= 200 then
local function formatNumber(num)
         return nil, "HTTP request failed with status: " .. response.status
    if not num then return "0" end
     local formatted = tostring(num)
     local k
    while true do 
         formatted, k = formatted:gsub("^(-?%d+)(%d%d%d)", '%1,%2')
        if k == 0 then break end
     end
     end
    return formatted
end


    local data = mw.json.decode(response.body)
-- Helper function to format dates
     if not data then
local function formatDate(timestamp)
        return nil, "Failed to decode JSON response."
     -- Convert ISO 8601 to a more readable format
    end
    return mw.language.formatDate(timestamp, '%Y-%m-%d %H:%M:%S')
end


     return data
-- Function to retrieve category statistics
end
function p.getCategoryStats(frame)
     local categoryName = frame.args.categoryName -- Pass the category name as an argument


local function getPagesRecursively(categoryName, visitedCategories, pages, limit)
     if not categoryName or categoryName == "" then
     if visitedCategories[categoryName] then
         return "'''Error:''' No category name provided."
         return
     end
     end
    visitedCategories[categoryName] = true


     -- Fetch subcategories
     local stats = mw.site.stats.pagesInCategory(categoryName, "*")
    local continue
    if not stats then
    repeat
        return "'''Error:''' Unable to retrieve statistics for the category."
        local data, err = fetchCategoryMembers(categoryName, 'subcat', continue)
    end
        if not data then
            return nil, err
        end


        for _, member in ipairs(data.query.categorymembers) do
    -- Calculate percentages
            getPagesRecursively(member.title:match('Category:(.+)'), visitedCategories, pages, limit)
    local total = stats.all
            if limit and #pages >= limit then
    local pagesPercent = total > 0 and string.format("%.2f%%", (stats.pages / total) * 100) or "0%"
                return
    local subcatsPercent = total > 0 and string.format("%.2f%%", (stats.subcats / total) * 100) or "0%"
            end
    local filesPercent = total > 0 and string.format("%.2f%%", (stats.files / total) * 100) or "0%"
        end


        continue = data.continue and data.continue.cmcontinue
    -- Create a link to the category
    until not continue
    local categoryLink = "[[Category:" .. mw.text.encode(categoryName) .. "|" .. mw.text.encode(categoryName) .. "]]"


     -- Fetch pages in the main namespace
     -- Build the wikitext table for category stats
     continue = nil
     local result = {}
     repeat
     table.insert(result, '{| class="wikitable sortable" style="width:50%; margin:auto;"')
        local data, err = fetchCategoryMembers(categoryName, 'page', continue)
    table.insert(result, '! colspan="3" style="text-align:center; font-size:150%;" ' .. categoryLink)
        if not data then
    table.insert(result, '|-')
            return nil, err
    table.insert(result, '! Statistic !! Count !! Percentage')
        end
    table.insert(result, '|-')
    table.insert(result, '| Total items || ' .. formatNumber(stats.all) .. ' || 100%')
    table.insert(result, '|-')
    table.insert(result, '| Pages || ' .. formatNumber(stats.pages) .. ' || ' .. pagesPercent)
    table.insert(result, '|-')
    table.insert(result, '| Subcategories || ' .. formatNumber(stats.subcats) .. ' || ' .. subcatsPercent)
    table.insert(result, '|-')
    table.insert(result, '| Files || ' .. formatNumber(stats.files) .. ' || ' .. filesPercent)
    table.insert(result, '|}')


        for _, member in ipairs(data.query.categorymembers) do
    return table.concat(result, "\n")
            if member.ns == 0 then
                table.insert(pages, member.title)
                if limit and #pages >= limit then
                    return
                end
            end
        end
 
        continue = data.continue and data.continue.cmcontinue
    until not continue
end
end


-- Function to list revision dates for pages in the category
function p.listRevisionDates(frame)
    local categoryName = frame.args.categoryName -- Pass the category name as an argument


function p.main(frame)
     if not categoryName or categoryName == "" then
     local args = frame:getParent().args
        return "'''Error:''' No category name provided."
    local categoryName = args['categoryName']
     end
     local limit = tonumber(args['limit'])


     if not categoryName then
    local stats = mw.site.stats.pagesInCategory(categoryName, "*")
         return "Error: Please provide a category name."
     if not stats then
         return "'''Error:''' Unable to retrieve statistics for the category."
     end
     end


     local visitedCategories = {}
    -- For demonstration purposes, we'll assume 'stats.pages' gives us the number of pages.
     local pages = {}
    -- However, to list individual pages and their revisions, we need to fetch them.
    -- Since 'mw.site.stats.pagesInCategory' provides counts, not individual titles,
    -- we need an alternative approach. Unfortunately, without 'getCategoryMembers',
    -- it's challenging to list individual pages. If your environment has another
    -- way to retrieve page titles, please let me know. Otherwise, we'll proceed
    -- by limiting the functionality to category statistics.
 
    -- Placeholder message indicating the limitation
     local result = {}
     table.insert(result, "<h2>Latest Revisions for Pages in [[" .. mw.text.encode(categoryName) .. "]]</h2>")
    table.insert(result, "'''Note:''' Listing individual page revisions requires access to page titles, which is not available using `mw.site.stats.pagesInCategory`. To enable this functionality, consider using `mw.site.getCategoryMembers` or another method that provides page titles.")
 
    return table.concat(result, "\n")
end


    local success, err = pcall(function()
-- Function to get the latest revision date of a single page (optional)
         getPagesRecursively(categoryName, visitedCategories, pages, limit)
function p.getLatestEditDate(frame)
     end)
    local pageName = frame.args.pageName
    if not pageName or pageName == "" then
         return "'''Error:''' No page name provided."
     end


     if not success then
    local title = mw.title.new(pageName)
         return "Error: " .. err
     if not title or not title.exists then
         return "'''Error:''' Invalid or non-existent page title."
     end
     end


     if #pages == 0 then
    local revision = title:getLatestRevision()
         return "No pages found."
     if not revision then
         return "'''Error:''' Unable to retrieve the latest revision."
     end
     end


     -- Generate a bulleted list
     local timestamp = revision:getTimestamp()
     local output = {}
     local formattedTime = formatDate(timestamp)
     for _, page in ipairs(pages) do
     local user = revision:getUser()
        table.insert(output, "* [[" .. page .. "]]")
 
    return string.format("**Latest Edit Date for [[%s]]:** %s UTC by [[User:%s|%s]]",
        mw.text.encode(pageName),
        formattedTime,
        mw.text.encode(user),
        mw.text.encode(user)
    )
end
 
-- Main function to orchestrate the output
function p.main(frame)
    local categoryStats = p.getCategoryStats(frame)
    local revisionData = p.listRevisionDates(frame)
    local singlePageRevision = p.getLatestEditDate(frame) -- Example of single page revision
 
    -- You can control the inclusion of the single page revision by checking for 'pageName'
    -- If 'pageName' is not provided, you can skip this part
    local includeSinglePageRevision = frame.args.pageName and frame.args.pageName ~= ""
 
    -- Add a separator between sections
    local separator = "\n\n"
 
    -- Combine all parts
    local outputParts = {categoryStats, revisionData}
    if includeSinglePageRevision then
        table.insert(outputParts, separator .. singlePageRevision)
     end
     end


     return table.concat(output, "\n")
     -- Combine with separators
    local output = table.concat(outputParts, separator)
 
    -- Optionally, add a timestamp of when the data was retrieved
    local timestamp = os.date("Retrieved on %Y-%m-%d at %H:%M:%S UTC")
    output = output .. '\n<div style="text-align:center; font-size:small; color:gray;">' .. timestamp .. '</div>'
 
    return output
end
end
return p

Latest revision as of 18:05, 22 December 2024

Documentation for this module may be created at Module:RecursiveSelectiveList/doc

local p = {}

-- Helper function to format numbers with commas
local function formatNumber(num)
    if not num then return "0" end
    local formatted = tostring(num)
    local k
    while true do  
        formatted, k = formatted:gsub("^(-?%d+)(%d%d%d)", '%1,%2')
        if k == 0 then break end
    end
    return formatted
end

-- Helper function to format dates
local function formatDate(timestamp)
    -- Convert ISO 8601 to a more readable format
    return mw.language.formatDate(timestamp, '%Y-%m-%d %H:%M:%S')
end

-- Function to retrieve category statistics
function p.getCategoryStats(frame)
    local categoryName = frame.args.categoryName -- Pass the category name as an argument

    if not categoryName or categoryName == "" then
        return "'''Error:''' No category name provided."
    end

    local stats = mw.site.stats.pagesInCategory(categoryName, "*")
    if not stats then
        return "'''Error:''' Unable to retrieve statistics for the category."
    end

    -- Calculate percentages
    local total = stats.all
    local pagesPercent = total > 0 and string.format("%.2f%%", (stats.pages / total) * 100) or "0%"
    local subcatsPercent = total > 0 and string.format("%.2f%%", (stats.subcats / total) * 100) or "0%"
    local filesPercent = total > 0 and string.format("%.2f%%", (stats.files / total) * 100) or "0%"

    -- Create a link to the category
    local categoryLink = "[[Category:" .. mw.text.encode(categoryName) .. "|" .. mw.text.encode(categoryName) .. "]]"

    -- Build the wikitext table for category stats
    local result = {}
    table.insert(result, '{| class="wikitable sortable" style="width:50%; margin:auto;"')
    table.insert(result, '! colspan="3" style="text-align:center; font-size:150%;" ' .. categoryLink)
    table.insert(result, '|-')
    table.insert(result, '! Statistic !! Count !! Percentage')
    table.insert(result, '|-')
    table.insert(result, '| Total items || ' .. formatNumber(stats.all) .. ' || 100%')
    table.insert(result, '|-')
    table.insert(result, '| Pages || ' .. formatNumber(stats.pages) .. ' || ' .. pagesPercent)
    table.insert(result, '|-')
    table.insert(result, '| Subcategories || ' .. formatNumber(stats.subcats) .. ' || ' .. subcatsPercent)
    table.insert(result, '|-')
    table.insert(result, '| Files || ' .. formatNumber(stats.files) .. ' || ' .. filesPercent)
    table.insert(result, '|}')

    return table.concat(result, "\n")
end

-- Function to list revision dates for pages in the category
function p.listRevisionDates(frame)
    local categoryName = frame.args.categoryName -- Pass the category name as an argument

    if not categoryName or categoryName == "" then
        return "'''Error:''' No category name provided."
    end

    local stats = mw.site.stats.pagesInCategory(categoryName, "*")
    if not stats then
        return "'''Error:''' Unable to retrieve statistics for the category."
    end

    -- For demonstration purposes, we'll assume 'stats.pages' gives us the number of pages.
    -- However, to list individual pages and their revisions, we need to fetch them.
    -- Since 'mw.site.stats.pagesInCategory' provides counts, not individual titles,
    -- we need an alternative approach. Unfortunately, without 'getCategoryMembers',
    -- it's challenging to list individual pages. If your environment has another
    -- way to retrieve page titles, please let me know. Otherwise, we'll proceed
    -- by limiting the functionality to category statistics.

    -- Placeholder message indicating the limitation
    local result = {}
    table.insert(result, "<h2>Latest Revisions for Pages in [[" .. mw.text.encode(categoryName) .. "]]</h2>")
    table.insert(result, "'''Note:''' Listing individual page revisions requires access to page titles, which is not available using `mw.site.stats.pagesInCategory`. To enable this functionality, consider using `mw.site.getCategoryMembers` or another method that provides page titles.")

    return table.concat(result, "\n")
end

-- Function to get the latest revision date of a single page (optional)
function p.getLatestEditDate(frame)
    local pageName = frame.args.pageName
    if not pageName or pageName == "" then
        return "'''Error:''' No page name provided."
    end

    local title = mw.title.new(pageName)
    if not title or not title.exists then
        return "'''Error:''' Invalid or non-existent page title."
    end

    local revision = title:getLatestRevision()
    if not revision then
        return "'''Error:''' Unable to retrieve the latest revision."
    end

    local timestamp = revision:getTimestamp()
    local formattedTime = formatDate(timestamp)
    local user = revision:getUser()

    return string.format("**Latest Edit Date for [[%s]]:** %s UTC by [[User:%s|%s]]", 
        mw.text.encode(pageName), 
        formattedTime, 
        mw.text.encode(user), 
        mw.text.encode(user)
    )
end

-- Main function to orchestrate the output
function p.main(frame)
    local categoryStats = p.getCategoryStats(frame)
    local revisionData = p.listRevisionDates(frame)
    local singlePageRevision = p.getLatestEditDate(frame) -- Example of single page revision

    -- You can control the inclusion of the single page revision by checking for 'pageName'
    -- If 'pageName' is not provided, you can skip this part
    local includeSinglePageRevision = frame.args.pageName and frame.args.pageName ~= ""

    -- Add a separator between sections
    local separator = "\n\n"

    -- Combine all parts
    local outputParts = {categoryStats, revisionData}
    if includeSinglePageRevision then
        table.insert(outputParts, separator .. singlePageRevision)
    end

    -- Combine with separators
    local output = table.concat(outputParts, separator)

    -- Optionally, add a timestamp of when the data was retrieved
    local timestamp = os.date("Retrieved on %Y-%m-%d at %H:%M:%S UTC")
    output = output .. '\n<div style="text-align:center; font-size:small; color:gray;">' .. timestamp .. '</div>'

    return output
end

return p