FANDOM


--|  Module:  DynamicWelcome (v1.4.0)
---  Allows for customizable welcome messages.
--by "The JoTS"
 
-- update v1.4.0 ~ Code snippet to convert wikilinks.
-- update v1.3.x ~ New user function for selecting greeter.
 
--TODO create message library for errors
-- <nowiki>
 
-- [==[ Import modules ]==] --
local getArgs = require("Dev:Arguments").getArgs
local yesno   = require "Dev:Yesno"
local custom, messages = pcall(mw.loadData, "Module:DynamicWelcome/msg")
 
-- 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, CHANCE = 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 "message" (see MODES)
--@ globals (table) Must be _G or getfenv()
--: (table) Formatted table
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")
    assert(type(globals.CHANCE) == "number" or globals.CHANCE == nil,
        "%Global \"CHANCE\" is defined, but is not a number value")
 
    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 {}
 
    -- setup greeter probability
    if admin ~= "Wikia" then
        frm[0] = frm[0] or {}
        table.insert(frm[0], {admin, globals.CHANCE or 1})
        globals.CHANCE = nil
    end
 
   -- 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
 
--% Selects a greeter based of chance and probability... or something
--: (string) Greeter's username
local function user()
    local probs = messages[0] or {} -- probabilities
    local totalProb = 0;
 
    for _,t in ipairs(probs) do
        totalProb = totalProb + t[2]
    end
 
    totalProb = math.ceil(totalProb)
 
    math.randomseed(os.time())
    local rand = math.random()
    local probSum = 0.0
 
    for _,t in ipairs(probs) do
        probSum = probSum + (t[2] / totalProb)
        if probSum >= rand then
            return t[1]
        end
    end
 
    -- something went wrong?
    return "@latest"
end
 
--% Converts a wikilink to a regular link (invoked in page source)
--- Prevents potential entry into Special:WantedPages upon deletion
--- Usage: {{#invoke:DynamicWelcome|link|$1}}
--@ frame (frame) Frame object.
--: (string) Formatted link
function link(frame)
    local args = frame.args
 
    if (not args[2]) then
        args = mw.text.split(args[1], '|')
    end
 
    return frame:preprocess(
        "[{{fullurl:" .. args[1] .. "}} " .. (args[2] or args[1]) .. "]")
end
 
--- Module interface ---------------------------
return {
    -- en
    greet = greet,    setup = setup,
    user  = user,     link  = link
}

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.