Fandom Developers Wiki
Register
Advertisement

This module was made as a sandbox for the user The JoTS. This documentation is kept to prevent redlinks.


--|  Module:  DynamicWelcome (v1.2.4)
---  Allows for customizable welcome messages.
--by "The JoTS"

-- update v1.2.4 ~ Internal code formatting, and removing function aliases.

--TODO create message library for errors
-- <nowiki>

-- [==[ Import modules ]==] --
local getArgs = require("Dev:Arguments").getArgs
local yesno   = require "Dev:Yesno"
local custom, messages =
    pcall(function() return mw.loadData "Module:DynamicWelcome/msg" end)

-- user error: msg dict exists, not formatted properly
if (not custom) and messages:match("^%%") then
    error(messages:sub(2))
end

--TODO implement default messages
--messages = custom and messages or mw.loadData "Dev:DynamicWelcome/default"

-- [==[ Meta functions ]==] --

--% Creates a wrapped function that returns an argument table to the provided
--- function 'func' and processes returned text from 'func'.
--@ func (function) A function to be wrapped.
--: (function) ...A wrapped function.
local function arg_wrap(func)
    return function(frame)
        return frame:preprocess( func(getArgs(frame)) )
    end
end

--% Returns the namespace of a given page name
--- or removes the namespace from a given page name, if 'gsub' is true.
--@ pageName (string) A page's name.
--@ gsub     (bool)   If true, removes the namespace from a page name.
--: (string) A string of a formatted page name, or of a namespace.
local function namespaceOp(pageName, gsub)
    -- consider splitting into two different funcs?
    return
        string[gsub and "gsub" or "match"](
            pageName,
            "^([^:]+):",
            gsub and '' or nil)
end

--% Dynamic processing of the "pipe trick," instead of at page save time.
--- See  http://wikipedia.org/wiki/Help:Pipe_trick  for more details.
--@ txt (string) Text to be processed.
--: (string) Processed string.
local function processPipeTrick(txt)
    -- the pipe trick involving the comma is NOT implemented
    
    return txt:gsub("%[%[([^|]+)|%]%]", function(page)
        -- get page name
        local name = page
            :gsub ("^[%w%s_]+:", '')
            :match "[%w%s_]+"
            :match "^%s*(.-)%s*$"
        
        -- return formatted link
        return "[[" .. page .. '|' .. name .. "]]"
    end)
end

--% Validates user input.
--@ provided (multiple) User input.
--@ options  (table)    Selection of possible inputs.
--: (multiple) ...I mean, in this script, it'll be a bool/nil.
--- Or, at the very least, it should be treated as such.
local function validate(provided, options)
    return options[provided]
end

-- [==[ Module Functions ]==] --
local MODES = {
    ["message-wall"] = true, ["message"] = true
}

local VAR_ENUM = {
    -- Implement custom enum for vars
    page        = 1, greeter_talk = 2,
    greeter_sig = 3, welcomed     = 4
}

local SETUP_CONST = {
    ADMIN = true, MODE = true, ANON = true
}

--% Generates a greeting message according the the provided args.
--@ vargs (table) A table of raw "virtual" arguments retrieved from frame.
--: (string) Generated greeting.
local function _greet(vargs)
    if vargs[5] then
        -- Handle a two part "page" argument (e.g. "Thread:1234|Lorem Ipsum")
        -- Does NOT properly handle an error in which a user
        -- somehow provides 5 args
        
        vargs[1] = vargs[1] .. '|' .. vargs[2] -- merge argument back together
        
        -- shift arguments in table
        for i=2,4 do
            vargs[i] = vargs[i + 1]
            vargs[i + 1] = nil
        end
    end

    -- Set enumerator
    local args = setmetatable({}, { __index = function(t, key)
        return vargs[VAR_ENUM[key] or key]
    end })
    
    assert((not args.mode) or validate(args.mode, MODES),
        "An invalid mode was provided")
    
    -- defaults
    args.mode = (type(args.mode) ~= "string" and "message-wall" or args.mode)
    args.anon = yesno(args.anon) and "anon" or "user"
    
    local dict  = messages[args.mode][args.anon] -- selected root dictionary
    
    -- Selected greeter dictionary ("Wikia" is fallback)
    local gDict = (not dict)
        and error("The \"" .. args.anon .. "\" dictionary does not exist")
        or dict[namespaceOp(args.greeter_talk, true)]
        or dict.Wikia
        or error("The default greeter dictionary,\"Wikia\", does not exist")
    
    local entry = gDict[namespaceOp(args.page)]
        or gDict.DEFAULT
        or error("The default entry does not exist")
    
    -- Return formatted entry
    return processPipeTrick( entry:gsub("%$(%d)", function(var)
        -- Substitute variable numbers w/ value
        return args[tonumber(var)] or var
    end) )
end

local greet = arg_wrap( _greet )

--% An assistive function for creating a table of greeting templates
--@ admin   (string) An admin to generate a greeting for.
--@ mode    (string) A messaging mode. "message-wall" or "
--@ globals (string) Must be _G or getfenv()
local function setup(admin, mode, globals)
    -- errors
    assert(globals.ADMIN == admin,
        "%Admin mismatch: " .. globals.ADMIN .. " x " .. admin)
    assert(globals.MODE == mode,
        "%Mode mismatch: " .. globals.MODE .. " x " .. mode)
    assert(validate(mode, MODES),
        "%An invalid mode was provided: " .. mode)
    assert(type(globals.ANON) == "boolean",
        "%Global \"ANON\" was not initialized or is not a boolean")
    
    local frm = globals.__DYNAWELC__ or {} -- formatted table
    local anon = globals.ANON and "anon" or "user"
    
    -- setup
    globals.__DYNAWELC__ = frm
    frm[mode] = frm[mode] or {}
    frm[mode][anon] = frm[mode][anon] or {}
    frm[mode][anon][admin] = frm[mode][anon][admin] or {}
   
   -- create entry 
    for k,v in pairs(globals) do
        if k:match("^(%u[%w_]+)$") and (not validate(k, SETUP_CONST)) then
            globals[k] = nil
            frm[mode][anon][admin][k:gsub('_',' ')] = v:gsub("\\n", "\n")
        end
    end

    return frm
end

--- Module interface ---------------------------
return {
    -- en
    greet = greet;
    setup = setup;
}
Advertisement