Potential slash-command compatibility, some code cleanup
parent
22581c242b
commit
f03a76897a
@ -0,0 +1,177 @@
|
||||
local discordia = require("discordia")
|
||||
local endpoints = require('./endpoints')
|
||||
local f = string.format
|
||||
local AC = require('./ApplicationCommand')
|
||||
local IA = require('./Interaction')
|
||||
local client_m = discordia.Client
|
||||
local guild_m = discordia.class.classes.Guild
|
||||
local cache_m = discordia.class.classes.Cache
|
||||
local enums = require('./enums')
|
||||
|
||||
local typeConverter = {
|
||||
[enums.optionType.string] = function(val) return val end,
|
||||
[enums.optionType.integer] = function(val) return val end,
|
||||
[enums.optionType.boolean] = function(val) return val end,
|
||||
[enums.optionType.user] = function(val, args) return args:getMember(val) end,
|
||||
[enums.optionType.channel] = function(val, args) return args:getChannel(val) end,
|
||||
[enums.optionType.role] = function(val, args) return args:getRole(val) end,
|
||||
}
|
||||
|
||||
local subCommand = enums.optionType.subCommand
|
||||
local subCommandGroup = enums.optionType.subCommandGroup
|
||||
|
||||
local function makeParams(data, guild, output)
|
||||
output = output or {}
|
||||
|
||||
for k, v in ipairs(data) do
|
||||
if v.type == subCommand or v.type == subCommandGroup then
|
||||
local t = {}
|
||||
output[v.name] = t
|
||||
makeParams(v.options, guild, t)
|
||||
else
|
||||
output[v.name] = typeConverter[v.type](v.value, guild)
|
||||
end
|
||||
end
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
function client_m:useSlashCommands()
|
||||
self._slashCommandsInjected = true
|
||||
|
||||
function self._events.INTERACTION_CREATE(args, client)
|
||||
local data = args.data
|
||||
local cmd = client:getSlashCommand(data.id)
|
||||
if not cmd then return client:warning('Uncached slash command (%s) on INTERACTION_CREATE', data.id) end
|
||||
if data.name ~= cmd._name then return client:warning('Slash command %s "%s" name doesn\'t match with interaction response, got "%s"! Guild %s, channel %s, member %s', cmd._id, cmd._name, data.name, args.guild_id, args.channel_id, args.member.user.id) end
|
||||
local ia = IA(args, client)
|
||||
local params = makeParams(data.options, ia.guild)
|
||||
local cb = cmd._callback
|
||||
if not cb then return client:warning('Unhandled slash command interaction: %s "%s" (%s)!', cmd._id, cmd._name, cmd._guild and "Guild " .. cmd._guild.id or "Global") end
|
||||
cb(ia, params, cmd)
|
||||
end
|
||||
|
||||
self:once("ready", function()
|
||||
local id = self:getApplicationInformation().id
|
||||
self._slashid = id
|
||||
self._globalCommands = {}
|
||||
self._guildCommands = {}
|
||||
self:getSlashCommands()
|
||||
self:emit("slashCommandsReady")
|
||||
end)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function client_m:slashCommand(data)
|
||||
local found
|
||||
|
||||
if not self._globalCommands then
|
||||
self:getSlashCommands()
|
||||
end
|
||||
|
||||
do
|
||||
local name = data.name
|
||||
|
||||
for _, v in pairs(self._globalCommands) do
|
||||
if v._name == name then
|
||||
found = v
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local cmd = AC(data, self)
|
||||
|
||||
if found then
|
||||
if not found:_compare(cmd) then
|
||||
found:_merge(cmd)
|
||||
elseif not found._callback then
|
||||
found._callback = cmd._callback
|
||||
end
|
||||
|
||||
return found
|
||||
else
|
||||
if cmd:publish() then
|
||||
self._globalCommands:_insert(cmd)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
return cmd
|
||||
end
|
||||
|
||||
function guild_m:slashCommand(data)
|
||||
local found
|
||||
|
||||
if not self._slashCommands then
|
||||
self:getSlashCommands()
|
||||
end
|
||||
|
||||
do
|
||||
local name = data.name
|
||||
|
||||
for _, v in pairs(self._slashCommands) do
|
||||
if v._name == name then
|
||||
found = v
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local cmd = AC(data, self)
|
||||
|
||||
if found then
|
||||
if not found:_compare(cmd) then
|
||||
found:_merge(cmd)
|
||||
elseif not found._callback then
|
||||
found._callback = cmd._callback
|
||||
end
|
||||
|
||||
return found
|
||||
else
|
||||
if cmd:publish() then
|
||||
self._slashCommands:_insert(cmd)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
return cmd
|
||||
end
|
||||
|
||||
function client_m:getSlashCommands()
|
||||
local list, err = self._api:request('GET', f(endpoints.COMMANDS, self._slashid))
|
||||
if not list then return nil, err end
|
||||
local cache = cache_m(list, AC, self)
|
||||
self._globalCommands = cache
|
||||
|
||||
return cache
|
||||
end
|
||||
|
||||
function guild_m:getSlashCommands()
|
||||
local list, err = self.client._api:request('GET', f(endpoints.COMMANDS_GUILD, self.client._slashid, self.id))
|
||||
if not list then return nil, err end
|
||||
local cache = cache_m(list, AC, self)
|
||||
self._slashCommands = cache
|
||||
self.client._guildCommands[self] = cache
|
||||
|
||||
return cache
|
||||
end
|
||||
|
||||
function client_m:getSlashCommand(id)
|
||||
if not self._globalCommands then
|
||||
self:getSlashCommands()
|
||||
end
|
||||
|
||||
local g = self._globalCommands:get(id)
|
||||
if g then return g end
|
||||
|
||||
for _, v in pairs(self._guildCommands) do
|
||||
g = v:get(id)
|
||||
if g then return g end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
@ -0,0 +1,283 @@
|
||||
local discordia = require("discordia")
|
||||
local endpoints = require('./endpoints')
|
||||
local f = string.format
|
||||
local Snowflake_m = discordia.class.classes.Snowflake
|
||||
local AC, ACgetters = discordia.class('ApplicationCommand', Snowflake_m)
|
||||
|
||||
local function recursiveOptionsMap(t)
|
||||
local map = {}
|
||||
|
||||
for _, v in ipairs(t) do
|
||||
local name = string.lower(v.name)
|
||||
v.name = name
|
||||
map[name] = v
|
||||
|
||||
if v.options then
|
||||
v.mapoptions = recursiveOptionsMap(v.options)
|
||||
end
|
||||
end
|
||||
|
||||
return map
|
||||
end
|
||||
|
||||
function AC:__init(data, parent)
|
||||
self._id = data.id
|
||||
self._parent = parent
|
||||
self._name = data.name
|
||||
self._description = data.description
|
||||
self._default_permission = data.default_permission
|
||||
self._version = data.version
|
||||
self._callback = data.callback
|
||||
self._guild = parent._id and parent
|
||||
|
||||
if not self._options then
|
||||
self._options = data.options or {}
|
||||
end
|
||||
end
|
||||
|
||||
function AC:publish()
|
||||
if self._id then return self:edit() end
|
||||
local g = self._guild
|
||||
|
||||
if not g then
|
||||
local res, err = self.client._api:request('POST', f(endpoints.COMMANDS, self.client._slashid), {
|
||||
name = self._name,
|
||||
description = self._description,
|
||||
options = self._options,
|
||||
default_permission = self._default_permission
|
||||
})
|
||||
|
||||
if not res then
|
||||
return nil, err
|
||||
else
|
||||
self._id = res.id
|
||||
|
||||
return self
|
||||
end
|
||||
else
|
||||
local res, err = self.client._api:request('POST', f(endpoints.COMMANDS_GUILD, self.client._slashid, g._id), {
|
||||
name = self._name,
|
||||
description = self._description,
|
||||
options = self._options,
|
||||
default_permission = self._default_permission
|
||||
})
|
||||
|
||||
if not res then
|
||||
return nil, err
|
||||
else
|
||||
self._id = res.id
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AC:edit()
|
||||
local g = self._guild
|
||||
|
||||
if not g then
|
||||
local res, err = self.client._api:request('PATCH', f(endpoints.COMMANDS_MODIFY, self.client._slashid, self._id), {
|
||||
name = self._name,
|
||||
description = self._description,
|
||||
options = self._options,
|
||||
default_permission = self._default_permission
|
||||
})
|
||||
|
||||
if not res then
|
||||
return nil, err
|
||||
else
|
||||
return true
|
||||
end
|
||||
else
|
||||
local res, err = self.client._api:request('PATCH', f(endpoints.COMMANDS_MODIFY_GUILD, self.client._slashid, g._id, self._id), {
|
||||
name = self._name,
|
||||
description = self._description,
|
||||
options = self._options,
|
||||
default_permission = self._default_permission
|
||||
})
|
||||
|
||||
if not res then
|
||||
return nil, err
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AC:setName(name)
|
||||
self._name = name
|
||||
end
|
||||
|
||||
function AC:setDescription(description)
|
||||
self._description = description
|
||||
end
|
||||
|
||||
function AC:setOptions(options)
|
||||
self._options = options
|
||||
end
|
||||
|
||||
function AC:setCallback(callback)
|
||||
self._callback = callback
|
||||
end
|
||||
|
||||
function AC:delete()
|
||||
local g = self._guild
|
||||
|
||||
if not g then
|
||||
self.client._api:request('DELETE', f(endpoints.COMMANDS_MODIFY, self.client._slashid, self._id))
|
||||
self.client._globalCommands:_delete(self._id)
|
||||
else
|
||||
self.client._api:request('DELETE', f(endpoints.COMMANDS_MODIFY_GUILD, self.client._slashid, g._id, self._id))
|
||||
g._slashCommands:_delete(self._id)
|
||||
end
|
||||
end
|
||||
|
||||
function AC:getPermissions(g)
|
||||
g = self._guild or g
|
||||
|
||||
if not g then
|
||||
error("Guild is required")
|
||||
end
|
||||
|
||||
local stat, err = self.client._api:request('GET', f(endpoints.COMMAND_PERMISSIONS_MODIFY, self.client._slashid, g._id, self._id))
|
||||
|
||||
if stat then
|
||||
return stat.permissions
|
||||
else
|
||||
return stat, err
|
||||
end
|
||||
end
|
||||
|
||||
function AC:addPermission(perm, g)
|
||||
g = self._guild or g
|
||||
|
||||
if not g then
|
||||
error("Guild is required")
|
||||
end
|
||||
|
||||
if not self._permissions then
|
||||
self._permissions = self:getPermissions(g) or {}
|
||||
end
|
||||
|
||||
for k, v in ipairs(self._permissions) do
|
||||
if v.id == perm.id and v.type == perm.type then
|
||||
if v.permission == perm.permission then return end
|
||||
self._permissions[k] = perm
|
||||
goto found
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
self._permissions[#self._permissions + 1] = perm
|
||||
end
|
||||
|
||||
::found::
|
||||
|
||||
return self.client._api:request('PUT', f(endpoints.COMMAND_PERMISSIONS_MODIFY, self.client._slashid, g._id, self._id), {
|
||||
permissions = self._permissions
|
||||
})
|
||||
end
|
||||
|
||||
function AC:removePermission(perm, g)
|
||||
g = self._guild or g
|
||||
|
||||
if not g then
|
||||
error("Guild is required")
|
||||
end
|
||||
|
||||
if not self._permissions then
|
||||
self._permissions = self:getPermissions(g) or {}
|
||||
end
|
||||
|
||||
for k, v in ipairs(self._permissions) do
|
||||
if v.id == perm.id and v.type == perm.type then
|
||||
table.remove(self._permissions, k)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return self.client._api:request('PUT', f(endpoints.COMMAND_PERMISSIONS_MODIFY, self.client._slashid, g._id, self._id), {
|
||||
permissions = self._permissions
|
||||
})
|
||||
end
|
||||
|
||||
local function recursiveCompare(a, b, checked)
|
||||
checked = checked or {}
|
||||
if checked[a] or checked[b] then return true end
|
||||
local inner_checked = {}
|
||||
|
||||
for k, v in pairs(a) do
|
||||
if type(v) == "table" and type(b[k]) == "table" then
|
||||
if not recursiveCompare(v, b[k], checked) then return false end
|
||||
elseif v ~= b[k] then
|
||||
print("k: ", k, "a[k]:", v, "b[k]: ", b[k])
|
||||
|
||||
return false
|
||||
else
|
||||
inner_checked[k] = true
|
||||
end
|
||||
end
|
||||
|
||||
for k, v in pairs(b) do
|
||||
if inner_checked[k] then
|
||||
goto skip
|
||||
end
|
||||
|
||||
if type(v) == "table" and type(a[k]) == "table" then
|
||||
if not recursiveCompare(v, a[k], checked) then return false end
|
||||
elseif v ~= a[k] then
|
||||
print("k: ", k, "a[k]:", a[k], "b[k]: ", v)
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
::skip::
|
||||
end
|
||||
|
||||
checked[a], checked[b] = true, true
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function AC:_compare(cmd)
|
||||
if self._name ~= cmd._name or self._description ~= cmd._description or self._default_permission ~= cmd._default_permission then return false end
|
||||
if not self._options and cmd._options then return false end
|
||||
if not recursiveCompare(self._options, cmd._options) then return false end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function AC:_merge(cmd)
|
||||
self._name = cmd._name
|
||||
self._description = cmd._description
|
||||
self._options = cmd._options
|
||||
self._callback = cmd._callback
|
||||
self._default_permission = cmd._default_permission
|
||||
self:edit()
|
||||
end
|
||||
|
||||
function ACgetters:name()
|
||||
return self._name
|
||||
end
|
||||
|
||||
function ACgetters:description()
|
||||
return self._description
|
||||
end
|
||||
|
||||
function ACgetters:options()
|
||||
return self._options
|
||||
end
|
||||
|
||||
function ACgetters:guild()
|
||||
return self._guild
|
||||
end
|
||||
|
||||
function ACgetters:callback()
|
||||
return self._callback
|
||||
end
|
||||
|
||||
function ACgetters:version()
|
||||
return self._version
|
||||
end
|
||||
|
||||
return AC
|
@ -0,0 +1,121 @@
|
||||
local discordia = require("discordia")
|
||||
local endpoints = require('./endpoints')
|
||||
local enums = require('./enums')
|
||||
local f = string.format
|
||||
local Snowflake_m = discordia.class.classes.Snowflake
|
||||
local IA, IAgetters = discordia.class('Interaction', Snowflake_m)
|
||||
|
||||
function IA:__init(data, parent)
|
||||
self._id = data.id
|
||||
self._parent = parent
|
||||
self._type = data.type
|
||||
self._token = data.token
|
||||
self._version = data.version
|
||||
local g = parent:getGuild(data.guild_id)
|
||||
if not g then return parent:warning('Uncached Guild (%s) on INTERACTION_CREATE', data.guild_id) end
|
||||
self._guild = g
|
||||
self._channel = g:getChannel(data.channel_id)
|
||||
self._member = g:getMember(data.member.user.id)
|
||||
end
|
||||
|
||||
function IA:createResponse(type, data)
|
||||
self._type = type
|
||||
|
||||
return self._parent._api:request('POST', f(endpoints.INTERACTION_RESPONSE, self._id, self._token), {
|
||||
type = type,
|
||||
data = data,
|
||||
})
|
||||
end
|
||||
|
||||
local deferredChannelMessageWithSource = enums.interactionResponseType.deferredChannelMessageWithSource
|
||||
local channelMessageWithSource = enums.interactionResponseType.channelMessageWithSource
|
||||
|
||||
function IA:ack()
|
||||
return self:createResponse(deferredChannelMessageWithSource)
|
||||
end
|
||||
|
||||
function IA:reply(data, private)
|
||||
if type(data) == "string" then
|
||||
data = {
|
||||
content = data
|
||||
}
|
||||
end
|
||||
|
||||
if private then
|
||||
data.flags = 64
|
||||
end
|
||||
|
||||
return self:createResponse(channelMessageWithSource, data)
|
||||
end
|
||||
|
||||
function IA:update(data)
|
||||
if type(data) == "string" then
|
||||
data = {
|
||||
content = data
|
||||
}
|
||||
end
|
||||
|
||||
return self._parent._api:request('PATCH', f(endpoints.INTERACTION_RESPONSE_MODIFY, self._parent._slashid, self._token), data)
|
||||
end
|
||||
|
||||
function IA:delete()
|
||||
return self._parent._api:request('DELETE', f(endpoints.INTERACTION_RESPONSE_MODIFY, self._parent._slashid, self._token))
|
||||
end
|
||||
|
||||
function IA:followUp(data, private)
|
||||
if type(data) == "string" then
|
||||
data = {
|
||||
content = data
|
||||
}
|
||||
end
|
||||
|
||||
if private then
|
||||
if self._type == deferredChannelMessageWithSource then
|
||||
private = false
|
||||
else
|
||||
data.flags = 64
|
||||
end
|
||||
end
|
||||
|
||||
local res = self._parent._api:request('POST', f(endpoints.INTERACTION_FOLLOWUP_CREATE, self._parent._slashid, self._token), data)
|
||||
|
||||
if res.id then
|
||||
local msg
|
||||
|
||||
if not private then
|
||||
msg = self._channel:getMessage(res.id)
|
||||
end
|
||||
|
||||
return res.id, msg, res
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
function IA:updateFollowUp(id, data)
|
||||
if type(data) == "string" then
|
||||
data = {
|
||||
content = data
|
||||
}
|
||||
end
|
||||
|
||||
return self._parent._api:request('PATCH', f(endpoints.INTERACTION_FOLLOWUP_MODIFY, self._parent._slashid, self._token, id), data)
|
||||
end
|
||||
|
||||
function IA:deleteFollowUp(id)
|
||||
return self._parent._api:request('DELETE', f(endpoints.INTERACTION_FOLLOWUP_MODIFY, self._parent._slashid, self._token, id))
|
||||
end
|
||||
|
||||
function IAgetters:guild()
|
||||
return self._guild
|
||||
end
|
||||
|
||||
function IAgetters:channel()
|
||||
return self._channel
|
||||
end
|
||||
|
||||
function IAgetters:member()
|
||||
return self._member
|
||||
end
|
||||
|
||||
return IA
|
@ -0,0 +1,227 @@
|
||||
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}
|
@ -0,0 +1,12 @@
|
||||
return {
|
||||
COMMANDS = "/applications/%s/commands",
|
||||
COMMANDS_GUILD = "/applications/%s/guilds/%s/commands",
|
||||
COMMANDS_MODIFY = "/applications/%s/commands/%s",
|
||||
COMMANDS_MODIFY_GUILD = "/applications/%s/guilds/%s/commands/%s",
|
||||
COMMAND_PERMISSIONS = "/applications/%s/guilds/%s/commands/permissions",
|
||||
COMMAND_PERMISSIONS_MODIFY = "/applications/%s/guilds/%s/commands/%s/permissions",
|
||||
INTERACTION_RESPONSE = "/interactions/%s/%s/callback",
|
||||
INTERACTION_RESPONSE_MODIFY = "/webhooks/%s/%s/messages/@original",
|
||||
INTERACTION_FOLLOWUP_CREATE = "/webhooks/%s/%s",
|
||||
INTERACTION_FOLLOWUP_MODIFY = "/webhooks/%s/%s/messages/%s"
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
local enum = require('discordia').enums.enum
|
||||
|
||||
return {
|
||||
optionType = enum({
|
||||
subCommand = 1,
|
||||
subCommandGroup = 2,
|
||||
string = 3,
|
||||
integer = 4,
|
||||
boolean = 5,
|
||||
user = 6,
|
||||
channel = 7,
|
||||
role = 8
|
||||
}),
|
||||
interactionType = enum({
|
||||
ping = 1,
|
||||
applicationCommand = 2
|
||||
}),
|
||||
interactionResponseType = enum({
|
||||
pong = 1,
|
||||
channelMessageWithSource = 4,
|
||||
deferredChannelMessageWithSource = 5
|
||||
}),
|
||||
applicationCommandPermissionType = enum({
|
||||
role = 1,
|
||||
user = 2,
|
||||
})
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
require("./Application")
|
||||
|
||||
local ret = {
|
||||
enums = require("./enums")
|
||||
}
|
||||
|
||||
ret.constructor = function()
|
||||
ret.new, ret.permission = unpack(require("./constructor"))
|
||||
end
|
||||
|
||||
return ret
|
@ -0,0 +1,15 @@
|
||||
return {
|
||||
name = 'GitSparTV/discordia-slash',
|
||||
description = 'Discordia 2.0 slash commands extension',
|
||||
version = '2.0.0',
|
||||
homepage = 'https://github.com/GitSparTV/discordia-slash',
|
||||
dependencies = {
|
||||
'SinisterRectus/discordia@2.8.4',
|
||||
},
|
||||
tags = {'discord', 'slash', 'discordia'},
|
||||
license = 'MIT',
|
||||
author = 'Spar',
|
||||
files = {
|
||||
'**.lua',
|
||||
},
|
||||
}
|
@ -1,3 +1,17 @@
|
||||
Hello!
|
||||
Line 2
|
||||
Line 3!
|
||||
```fix
|
||||
Basic functions
|
||||
---------------
|
||||
-ping
|
||||
Pong!
|
||||
-roll
|
||||
Rolls a d20
|
||||
-time
|
||||
Displays the time in military time, as if you were in chicago
|
||||
-help
|
||||
^-^
|
||||
Basic Information
|
||||
-----------------
|
||||
All functions start with '!' though this may change in the future
|
||||
Under construction! More or less from scratch(Only just got basic I/O working!)
|
||||
May have secret functions!
|
||||
```
|
||||
|
@ -1 +1 @@
|
||||
{"873255296024322059":{"timestamp":1628279979,"owner":{"username":"team872299874857676820","id":"872299874857676820","public_flags":1024,"flags":1024,"discriminator":"0000","avatar":null},"shards":1},"url":"wss://gateway.discord.gg"}
|
||||
{"873255296024322059":{"timestamp":1628283774,"owner":{"discriminator":"0000","avatar":null,"id":"872299874857676820","flags":1024,"public_flags":1024,"username":"team872299874857676820"},"shards":1},"url":"wss://gateway.discord.gg"}
|
Loading…
Reference in New Issue