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.

282 lines
7.3 KiB
Lua

--[=[
@c GuildChannel x Channel
@t abc
@d Defines the base methods and properties for all Discord guild channels.
]=]
local json = require('json')
local enums = require('enums')
local class = require('class')
local Channel = require('containers/abstract/Channel')
local PermissionOverwrite = require('containers/PermissionOverwrite')
local Invite = require('containers/Invite')
local Cache = require('iterables/Cache')
local Resolver = require('client/Resolver')
local isInstance = class.isInstance
local classes = class.classes
local channelType = enums.channelType
local insert, sort = table.insert, table.sort
local min, max, floor = math.min, math.max, math.floor
local huge = math.huge
local GuildChannel, get = class('GuildChannel', Channel)
function GuildChannel:__init(data, parent)
Channel.__init(self, data, parent)
self.client._channel_map[self._id] = parent
self._permission_overwrites = Cache({}, PermissionOverwrite, self)
return self:_loadMore(data)
end
function GuildChannel:_load(data)
Channel._load(self, data)
return self:_loadMore(data)
end
function GuildChannel:_loadMore(data)
return self._permission_overwrites:_load(data.permission_overwrites, true)
end
--[=[
@m setName
@t http
@p name string
@r boolean
@d Sets the channel's name. This must be between 2 and 100 characters in length.
]=]
function GuildChannel:setName(name)
return self:_modify({name = name or json.null})
end
--[=[
@m setCategory
@t http
@p id Channel-ID-Resolvable
@r boolean
@d Sets the channel's parent category.
]=]
function GuildChannel:setCategory(id)
id = Resolver.channelId(id)
return self:_modify({parent_id = id or json.null})
end
local function sorter(a, b)
if a.position == b.position then
return tonumber(a.id) < tonumber(b.id)
else
return a.position < b.position
end
end
local function getSortedChannels(self)
local channels
local t = self._type
if t == channelType.text or t == channelType.news then
channels = self._parent._text_channels
elseif t == channelType.voice then
channels = self._parent._voice_channels
elseif t == channelType.category then
channels = self._parent._categories
end
local ret = {}
for channel in channels:iter() do
insert(ret, {id = channel._id, position = channel._position})
end
sort(ret, sorter)
return ret
end
local function setSortedChannels(self, channels)
local data, err = self.client._api:modifyGuildChannelPositions(self._parent._id, channels)
if data then
return true
else
return false, err
end
end
--[=[
@m moveUp
@t http
@p n number
@r boolean
@d Moves a channel up its list. The parameter `n` indicates how many spaces the
channel should be moved, clamped to the highest position, with a default of 1 if
it is omitted. This will also normalize the positions of all channels.
]=]
function GuildChannel:moveUp(n)
n = tonumber(n) or 1
if n < 0 then
return self:moveDown(-n)
end
local channels = getSortedChannels(self)
local new = huge
for i = #channels - 1, 0, -1 do
local v = channels[i + 1]
if v.id == self._id then
new = max(0, i - floor(n))
v.position = new
elseif i >= new then
v.position = i + 1
else
v.position = i
end
end
return setSortedChannels(self, channels)
end
--[=[
@m moveDown
@t http
@p n number
@r boolean
@d Moves a channel down its list. The parameter `n` indicates how many spaces the
channel should be moved, clamped to the lowest position, with a default of 1 if
it is omitted. This will also normalize the positions of all channels.
]=]
function GuildChannel:moveDown(n)
n = tonumber(n) or 1
if n < 0 then
return self:moveUp(-n)
end
local channels = getSortedChannels(self)
local new = -huge
for i = 0, #channels - 1 do
local v = channels[i + 1]
if v.id == self._id then
new = min(i + floor(n), #channels - 1)
v.position = new
elseif i <= new then
v.position = i - 1
else
v.position = i
end
end
return setSortedChannels(self, channels)
end
--[=[
@m createInvite
@t http
@op payload table
@r Invite
@d Creates an invite to the channel. Optional payload fields are: max_age: number
time in seconds until expiration, default = 86400 (24 hours), max_uses: number
total number of uses allowed, default = 0 (unlimited), temporary: boolean whether
the invite grants temporary membership, default = false, unique: boolean whether
a unique code should be guaranteed, default = false
]=]
function GuildChannel:createInvite(payload)
local data, err = self.client._api:createChannelInvite(self._id, payload)
if data then
return Invite(data, self.client)
else
return nil, err
end
end
--[=[
@m getInvites
@t http
@r Cache
@d Returns a newly constructed cache of all invite objects for the channel. The
cache and its objects are not automatically updated via gateway events. You must
call this method again to get the updated objects.
]=]
function GuildChannel:getInvites()
local data, err = self.client._api:getChannelInvites(self._id)
if data then
return Cache(data, Invite, self.client)
else
return nil, err
end
end
--[=[
@m getPermissionOverwriteFor
@t mem
@p obj Role/Member
@r PermissionOverwrite
@d Returns a permission overwrite object corresponding to the provided member or
role object. If a cached overwrite is not found, an empty overwrite with
zero-permissions is returned instead. Therefore, this can be used to create a
new overwrite when one does not exist. Note that the member or role must exist
in the same guild as the channel does.
]=]
function GuildChannel:getPermissionOverwriteFor(obj)
local id, type
if isInstance(obj, classes.Role) and self._parent == obj._parent then
id, type = obj._id, 'role'
elseif isInstance(obj, classes.Member) and self._parent == obj._parent then
id, type = obj._user._id, 'member'
else
return nil, 'Invalid Role or Member: ' .. tostring(obj)
end
local overwrites = self._permission_overwrites
return overwrites:get(id) or overwrites:_insert(setmetatable({
id = id, type = type, allow = 0, deny = 0
}, {__jsontype = 'object'}))
end
--[=[
@m delete
@t http
@r boolean
@d Permanently deletes the channel. This cannot be undone!
]=]
function GuildChannel:delete()
return self:_delete()
end
--[=[@p permissionOverwrites Cache An iterable cache of all overwrites that exist in this channel. To access an
overwrite that may exist, but is not cached, use `GuildChannel:getPermissionOverwriteFor`.]=]
function get.permissionOverwrites(self)
return self._permission_overwrites
end
--[=[@p name string The name of the channel. This should be between 2 and 100 characters in length.]=]
function get.name(self)
return self._name
end
--[=[@p position number The position of the channel, where 0 is the highest.]=]
function get.position(self)
return self._position
end
--[=[@p guild Guild The guild in which this channel exists.]=]
function get.guild(self)
return self._parent
end
--[=[@p category GuildCategoryChannel/nil The parent channel category that may contain this channel.]=]
function get.category(self)
return self._parent._categories:get(self._parent_id)
end
--[=[@p private boolean Whether the "everyone" role has permission to view this
channel. In the Discord channel, private text channels are indicated with a lock
icon and private voice channels are not visible.]=]
function get.private(self)
local overwrite = self._permission_overwrites:get(self._parent._id)
return overwrite and overwrite:getDeniedPermissions():has('readMessages')
end
return GuildChannel