Module:DynamicWelcome

--| 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 --

-- [==[ 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 "' .. 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; }