local optionMeta = {} optionMeta.__index = optionMeta function optionMeta:option(name, description, type, required) if not name then error("Name is required") elseif not description then error("Description is required") elseif not type then error("Type is required") elseif #name == 0 or #name > 32 then error("Must be between 1 and 32 in length") elseif string.find(name, "^[^%w_-]$") then error("The name should match ^[\\w-]{1,32}$ pattern") elseif #description == 0 or #description > 100 then error("Must be between 1 and 100 in length") elseif type < 1 or type > 8 then error("Value type must be between 1 and 8 (See ApplicationCommandOptionType)") end local ctnr = self[1] local selfType = ctnr.type if not self[2] then if selfType <= 2 then if (selfType == 1 and type <= 2) or (selfType == 2 and type == 2) then error("Nesting of sub-commands is unsupported at this time") end else error("Sub-options cannot be configured for this type of option") end end local t = setmetatable({ parent = self, { name = name, description = description, type = type, } }, optionMeta) if not ctnr.options then ctnr.options = {} end ctnr.options[#ctnr.options + 1] = t if required then t:required() end return t end function optionMeta:suboption(name, description) return self:option(name, description, 1) end function optionMeta:group(name, description) return self:option(name, description, 2) end function optionMeta:required(no) local ctnr = self[1] local type = ctnr.type if type <= 2 then error("Required cannot be configured for this type of option") end for _, v in ipairs(self.parent[1].options) do if not v.required then error("Required options must be placed before non-required options") end if v == self then break end end ctnr.required = not no end -- function optionMeta:default(no) -- local ctnr = self[1] -- local type = ctnr.type -- if type <= 2 then -- error("Default cannot be configured for this type of option") -- end -- if not self[1].required then -- error("Default cannot be configured with required = false") -- end -- for _, v in ipairs(self.parent[1].options) do -- if v[1].default then -- error("There can be 1 default option within command, sub-command, and sub-command group options") -- end -- end -- ctnr.default = not no -- end function optionMeta:choices(...) local ctnr = self[1] local opttype = ctnr.type local acceptedType if opttype == 3 then acceptedType = "string" elseif opttype == 4 then acceptedType = "number" else error("Choices cannot be configured for this type of option") end local t = {} ctnr.choices = t for i = 1, select("#", ...) do local v = select(i, ...) if type(v) == acceptedType then t[i] = { name = tostring(v), value = v } else t[i] = v end end end function optionMeta:finish() local t = {} for k, v in pairs(self[1]) do t[k] = v end if t.options then local options = {} for k, v in ipairs(t.options) do options[k] = v:finish() end t.options = options end return t end local commandMeta = {} commandMeta.__index = commandMeta commandMeta.option = optionMeta.option commandMeta.finish = optionMeta.finish commandMeta.suboption = optionMeta.suboption commandMeta.group = optionMeta.group function commandMeta:disableForEveryone(no) if not no then no = false end self[1].default_permission = no end function commandMeta:callback(cb) self[1].callback = cb end local function new(name, description, cb) if not name then error("Name is required") elseif not description then error("Description is required") elseif #name == 0 or #name > 32 then error("Must be between 1 and 32 in length") elseif string.find(name, "^[^%w_-]$") then error("The name should match ^[\\w-]{1,32}$ pattern") elseif #description == 0 or #description > 100 then error("Must be between 1 and 100 in length") end return setmetatable({ { name = name, description = description, options = {}, default_permission = true, callback = cb }, true }, commandMeta) end local discordia = require("discordia") local enums = require("./enums") local enum_user = enums.applicationCommandPermissionType.user local enum_role = enums.applicationCommandPermissionType.role local function perm(obj, allow, _type) if type(obj) == "string" then if not _type then error("Type required") end return { id = obj, type = _type, permission = allow and true or false } end local t = discordia.class.type(obj) if t == "Member" or t == "User" then _type = enum_user elseif t == "Role" then _type = enum_role end return { id = obj.id, type = _type, permission = allow and true or false } end return {new, perm}