Module:RandomGalleryAny

Lua
CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules

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

Code

--[[
    Module:RandomGalleryAny
    
    This module reads the content of a specified wiki page, extracts each line
    that appears to be a filename (allowing for captions/wikitext after a pipe |),
    shuffles the list, and outputs a subset formatted as a <gallery> block with mode="packed".
--]]

local p = {}

-- 1. Helper function to trim whitespace (Defined on p table)
p.trim = function(s)
    return s:match('^%s*(.*%S)%s*$') or ''
end

-- 2. HASHING FUNCTION: Generates a reliable integer seed from any string (Defined on p table)
p.string_to_seed = function(s)
    local hash = 0
    s = tostring(s) 
    
    for i = 1, #s do
        hash = hash + s:byte(i)
        hash = (hash * 65599) % 2147483647
    end
    if hash == 0 then return os.time() end
    return hash
end

-- 3. Function to check if a line is likely an image file line (Defined on p table)
p.is_image_line = function(line)
    -- This pattern looks for a common file extension (.jpg, .png, .gif, .svg, etc.)
    -- Can start with File: or not
    local extensions = {
        '[%.][Jj][Pp][Ee]?[Gg]',
        '[%.][Pp][Nn][Gg]',
        '[%.][Gg][Ii][Ff]',
        '[%.][Ss][Vv][Gg]',
        '[%.][Tt][Ii][Ff][Ff]?',
        '[%.][Bb][Mm][Pp]',
        '[%.][Ww][Ee][Bb][Pp]',
        '[%.][Jj][Pp][Ee][Gg]',
        '[%.][Jj][2][Kk]',
        '[%.][Cc][Ee][Ff]',
        '[%.][Pp][Dd][Ff]',
        '[%.][Dd][Jj][Vv][Uu]'
    }
    
    for _, ext in ipairs(extensions) do
        if line:match(ext) then
            return true
        end
    end
    return false
end

-- 4. Function to normalize the filename (ensure it doesn't have File: prefix for gallery)
p.normalize_line = function(line)
    -- Gallery tags don't need the "File:" prefix, so we remove it if present
    -- but preserve everything else (including captions after |)
    local normalized = line:gsub('^%s*[Ff][Ii][Ll][Ee]%s*:%s*', '')
    return normalized
end

-- 5. Function to perform the Fisher-Yates shuffle (Defined on p table)
p.shuffle = function(t)
    local n = #t
    local rand = math.random
    while n >= 2 do
        local k = rand(n)
        t[n], t[k] = t[k], t[n]
        n = n - 1
    end
    return t
end

-- Main function
function p.showRandom(frame)
    
    local args = frame:getParent().args
    local page_title = args[1]
    local height = tonumber(args['height'] or args[2] or 200)
    local count = tonumber(args['count'] or args[3] or 12)
    local seed = args['seed'] or args[4] or os.time()
    local debug = args['debug']

    if not page_title then
        return '<span style="color: red; font-weight: bold;">Error: Missing required parameter 1 (page list title).</span>'
    end
    
    -- Use hashing to generate a safe integer seed
    local final_seed = p.string_to_seed(seed)
    
    -- Set the seed for randomization
    math.randomseed(final_seed)

    -- Get the content of the specified page
    local title = mw.title.new(page_title)
    if not title or not title.exists then
        return '<span style="color: red; font-weight: bold;">Error: Page does not exist: ' .. page_title .. '</span>'
    end
    
    local page_content = title:getContent()

    if not page_content then
        return '<span style="color: red; font-weight: bold;">Error: Could not retrieve content for page: ' .. page_title .. '</span>'
    end

    local image_list = {}
    
    -- Split the content into lines and filter for image lines
    local lines = mw.text.split(page_content, '\n')
    for _, line in ipairs(lines) do
        local trimmed_line = p.trim(line)
        -- Check if this line contains an image file
        if trimmed_line ~= '' and p.is_image_line(trimmed_line) then
            -- Normalize the line (remove File: prefix if present)
            local normalized = p.normalize_line(trimmed_line)
            table.insert(image_list, normalized)
        end
    end

    if #image_list == 0 then
        return '<span style="color: orange;">Warning: The list page is empty or contains no valid file entries: ' .. page_title .. '</span>'
    end

    -- Shuffle the list
    local shuffled_list = p.shuffle(image_list)

    -- Select the requested number of items
    local final_items = {}
    for i = 1, math.min(count, #shuffled_list) do
        table.insert(final_items, shuffled_list[i])
    end

    -- Construct the output gallery
    local output = {}
    
    -- Uses mode="packed" as requested (This displays the captions)
    table.insert(output, '<gallery mode="packed" heights="' .. height .. '">')
    
    -- Add the selected items (which include the full filename and caption/wikitext)
    for _, item in ipairs(final_items) do
        table.insert(output, item)
    end
    
    table.insert(output, '</gallery>')

    if debug then
        table.insert(output, '<div style="border: 1px solid #ccc; padding: 5px; margin-top: 10px; background: #f9f9f9;">')
        table.insert(output, '<b>DEBUG OUTPUT</b><br/>')
        table.insert(output, 'Page: ' .. page_title .. '<br/>')
        table.insert(output, 'Total Items Found: ' .. #image_list .. '<br/>')
        table.insert(output, 'Items Selected: ' .. #final_items .. '<br/>')
        table.insert(output, 'Seed: ' .. tostring(seed) .. ' (hashed to: ' .. final_seed .. ')<br/>')
        table.insert(output, '<hr/>')
        table.insert(output, '<b>Selected Items:</b><br/>')
        for i, item in ipairs(final_items) do
            table.insert(output, i .. '. <code>' .. mw.text.encode(item) .. '</code><br/>')
        end
        table.insert(output, '</div>')
    end

    local result = table.concat(output, '\n')
    
    -- Preprocess the output so the gallery tag is properly parsed
    return frame:preprocess(result)
end

return p