You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
4.4 KiB
Lua

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