2022-03-19 10:37:45 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const process = require('node:process');
|
|
|
|
const { Collection } = require('@discordjs/collection');
|
|
|
|
const CachedManager = require('./CachedManager');
|
|
|
|
const { TypeError } = require('../errors');
|
|
|
|
const PermissionOverwrites = require('../structures/PermissionOverwrites');
|
|
|
|
const { Role } = require('../structures/Role');
|
2022-03-24 10:55:32 +00:00
|
|
|
const { OverwriteTypes } = require('../util/Constants');
|
2022-03-19 10:37:45 +00:00
|
|
|
|
|
|
|
let cacheWarningEmitted = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Manages API methods for guild channel permission overwrites and stores their cache.
|
|
|
|
* @extends {CachedManager}
|
|
|
|
*/
|
|
|
|
class PermissionOverwriteManager extends CachedManager {
|
|
|
|
constructor(channel, iterable) {
|
|
|
|
super(channel.client, PermissionOverwrites);
|
|
|
|
if (!cacheWarningEmitted && this._cache.constructor.name !== 'Collection') {
|
|
|
|
cacheWarningEmitted = true;
|
|
|
|
process.emitWarning(
|
|
|
|
`Overriding the cache handling for ${this.constructor.name} is unsupported and breaks functionality.`,
|
|
|
|
'UnsupportedCacheOverwriteWarning',
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The channel of the permission overwrite this manager belongs to
|
|
|
|
* @type {GuildChannel}
|
|
|
|
*/
|
|
|
|
this.channel = channel;
|
|
|
|
|
|
|
|
if (iterable) {
|
|
|
|
for (const item of iterable) {
|
|
|
|
this._add(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The cache of this Manager
|
|
|
|
* @type {Collection<Snowflake, PermissionOverwrites>}
|
|
|
|
* @name PermissionOverwriteManager#cache
|
|
|
|
*/
|
|
|
|
|
|
|
|
_add(data, cache) {
|
|
|
|
return super._add(data, cache, { extras: [this.channel] });
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replaces the permission overwrites in this channel.
|
|
|
|
* @param {OverwriteResolvable[]|Collection<Snowflake, OverwriteResolvable>} overwrites
|
|
|
|
* Permission overwrites the channel gets updated with
|
|
|
|
* @param {string} [reason] Reason for updating the channel overwrites
|
|
|
|
* @returns {Promise<GuildChannel>}
|
|
|
|
* @example
|
|
|
|
* message.channel.permissionOverwrites.set([
|
|
|
|
* {
|
|
|
|
* id: message.author.id,
|
2022-03-24 10:55:32 +00:00
|
|
|
* deny: [Permissions.FLAGS.VIEW_CHANNEL],
|
2022-03-19 10:37:45 +00:00
|
|
|
* },
|
|
|
|
* ], 'Needed to change permissions');
|
|
|
|
*/
|
|
|
|
set(overwrites, reason) {
|
|
|
|
if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) {
|
|
|
|
return Promise.reject(
|
|
|
|
new TypeError('INVALID_TYPE', 'overwrites', 'Array or Collection of Permission Overwrites', true),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return this.channel.edit({ permissionOverwrites: overwrites, reason });
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extra information about the overwrite
|
|
|
|
* @typedef {Object} GuildChannelOverwriteOptions
|
|
|
|
* @property {string} [reason] Reason for creating/editing this overwrite
|
|
|
|
* @property {number} [type] The type of overwrite, either `0` for a role or `1` for a member. Use this to bypass
|
|
|
|
* automatic resolution of type that results in an error for uncached structure
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates or edits permission overwrites for a user or role in this channel.
|
|
|
|
* @param {RoleResolvable|UserResolvable} userOrRole The user or role to update
|
|
|
|
* @param {PermissionOverwriteOptions} options The options for the update
|
|
|
|
* @param {GuildChannelOverwriteOptions} [overwriteOptions] The extra information for the update
|
|
|
|
* @param {PermissionOverwrites} [existing] The existing overwrites to merge with this update
|
|
|
|
* @returns {Promise<GuildChannel>}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
async upsert(userOrRole, options, overwriteOptions = {}, existing) {
|
2022-04-16 10:44:43 +00:00
|
|
|
const userOrRoleId = this.channel.guild.roles.resolveId(userOrRole) ?? this.client.users.resolveId(userOrRole);
|
2022-03-19 10:37:45 +00:00
|
|
|
let { type, reason } = overwriteOptions;
|
|
|
|
if (typeof type !== 'number') {
|
|
|
|
userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole);
|
|
|
|
if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role');
|
2022-03-24 10:55:32 +00:00
|
|
|
type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member;
|
2022-03-19 10:37:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options, existing);
|
|
|
|
|
2022-03-24 10:55:32 +00:00
|
|
|
await this.client.api
|
|
|
|
.channels(this.channel.id)
|
|
|
|
.permissions(userOrRoleId)
|
|
|
|
.put({
|
|
|
|
data: { id: userOrRoleId, type, allow, deny },
|
|
|
|
reason,
|
|
|
|
});
|
2022-03-19 10:37:45 +00:00
|
|
|
return this.channel;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates permission overwrites for a user or role in this channel, or replaces them if already present.
|
|
|
|
* @param {RoleResolvable|UserResolvable} userOrRole The user or role to update
|
|
|
|
* @param {PermissionOverwriteOptions} options The options for the update
|
|
|
|
* @param {GuildChannelOverwriteOptions} [overwriteOptions] The extra information for the update
|
|
|
|
* @returns {Promise<GuildChannel>}
|
|
|
|
* @example
|
|
|
|
* // Create or Replace permission overwrites for a message author
|
|
|
|
* message.channel.permissionOverwrites.create(message.author, {
|
|
|
|
* SEND_MESSAGES: false
|
|
|
|
* })
|
|
|
|
* .then(channel => console.log(channel.permissionOverwrites.cache.get(message.author.id)))
|
|
|
|
* .catch(console.error);
|
|
|
|
*/
|
|
|
|
create(userOrRole, options, overwriteOptions) {
|
|
|
|
return this.upsert(userOrRole, options, overwriteOptions);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Edits permission overwrites for a user or role in this channel, or creates an entry if not already present.
|
|
|
|
* @param {RoleResolvable|UserResolvable} userOrRole The user or role to update
|
|
|
|
* @param {PermissionOverwriteOptions} options The options for the update
|
|
|
|
* @param {GuildChannelOverwriteOptions} [overwriteOptions] The extra information for the update
|
|
|
|
* @returns {Promise<GuildChannel>}
|
|
|
|
* @example
|
|
|
|
* // Edit or Create permission overwrites for a message author
|
|
|
|
* message.channel.permissionOverwrites.edit(message.author, {
|
|
|
|
* SEND_MESSAGES: false
|
|
|
|
* })
|
|
|
|
* .then(channel => console.log(channel.permissionOverwrites.cache.get(message.author.id)))
|
|
|
|
* .catch(console.error);
|
|
|
|
*/
|
|
|
|
edit(userOrRole, options, overwriteOptions) {
|
2022-07-17 17:58:28 +00:00
|
|
|
const existing = this.cache.get(
|
|
|
|
this.channel.guild.roles.resolveId(userOrRole) ?? this.client.users.resolveId(userOrRole),
|
|
|
|
);
|
2022-03-19 10:37:45 +00:00
|
|
|
return this.upsert(userOrRole, options, overwriteOptions, existing);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deletes permission overwrites for a user or role in this channel.
|
|
|
|
* @param {UserResolvable|RoleResolvable} userOrRole The user or role to delete
|
|
|
|
* @param {string} [reason] The reason for deleting the overwrite
|
|
|
|
* @returns {Promise<GuildChannel>}
|
|
|
|
*/
|
|
|
|
async delete(userOrRole, reason) {
|
|
|
|
const userOrRoleId = this.channel.guild.roles.resolveId(userOrRole) ?? this.client.users.resolveId(userOrRole);
|
|
|
|
if (!userOrRoleId) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role');
|
|
|
|
|
|
|
|
await this.client.api.channels(this.channel.id).permissions(userOrRoleId).delete({ reason });
|
|
|
|
return this.channel;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = PermissionOverwriteManager;
|