Skip to content

Commit

Permalink
refactor(PermissionOverwrites)!: cache-independent resolve (discordjs…
Browse files Browse the repository at this point in the history
…#10528)

BREAKING CHANGE: `PermissionOverwrites#resolve`'s `overwrite` arg now requires `type` if the `id` is a Snowflake
  • Loading branch information
Renegade334 authored Jan 3, 2025
1 parent 9fea069 commit bacc08b
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 13 deletions.
6 changes: 6 additions & 0 deletions packages/discord.js/src/errors/ErrorCodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@
* @property {'BulkBanUsersOptionEmpty'} BulkBanUsersOptionEmpty
* @property {'PollAlreadyExpired'} PollAlreadyExpired
* @property {'PermissionOverwritesTypeMandatory'} PermissionOverwritesTypeMandatory
* @property {'PermissionOverwritesTypeMismatch'} PermissionOverwritesTypeMismatch
*/

const keys = [
Expand Down Expand Up @@ -258,6 +261,9 @@ const keys = [
'BulkBanUsersOptionEmpty',

'PollAlreadyExpired',

'PermissionOverwritesTypeMandatory',
'PermissionOverwritesTypeMismatch',
];

// JSDoc for IntelliSense purposes
Expand Down
5 changes: 5 additions & 0 deletions packages/discord.js/src/errors/Messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ const Messages = {
[DjsErrorCodes.BulkBanUsersOptionEmpty]: 'Option "users" array or collection is empty',

[DjsErrorCodes.PollAlreadyExpired]: 'This poll has already expired.',

[DjsErrorCodes.PermissionOverwritesTypeMandatory]: '"overwrite.type" is mandatory if "overwrite.id" is a Snowflake',
[DjsErrorCodes.PermissionOverwritesTypeMismatch]: expected =>
`"overwrite.id" is a ${expected.toLowerCase()} object, ` +
`but "overwrite.type" is defined and not equal to OverwriteType.${expected}`,
};

module.exports = Messages;
34 changes: 22 additions & 12 deletions packages/discord.js/src/structures/PermissionOverwrites.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class PermissionOverwrites extends Base {
* @property {GuildMemberResolvable|RoleResolvable} id Member or role this overwrite is for
* @property {PermissionResolvable} [allow] The permissions to allow
* @property {PermissionResolvable} [deny] The permissions to deny
* @property {OverwriteType} [type] The type of this OverwriteData
* @property {OverwriteType} [type] The type of this OverwriteData (mandatory if `id` is a Snowflake)
*/

/**
Expand All @@ -171,21 +171,31 @@ class PermissionOverwrites extends Base {
*/
static resolve(overwrite, guild) {
if (overwrite instanceof this) return overwrite.toJSON();
if (typeof overwrite.id === 'string' && overwrite.type in OverwriteType) {
return {
id: overwrite.id,
type: overwrite.type,
allow: PermissionsBitField.resolve(overwrite.allow ?? PermissionsBitField.DefaultBit).toString(),
deny: PermissionsBitField.resolve(overwrite.deny ?? PermissionsBitField.DefaultBit).toString(),
};

const id = guild.roles.resolveId(overwrite.id) ?? guild.client.users.resolveId(overwrite.id);
if (!id) {
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'overwrite.id', 'GuildMemberResolvable or RoleResolvable');
}

if (overwrite.type !== undefined && (typeof overwrite.type !== 'number' || !(overwrite.type in OverwriteType))) {
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'overwrite.type', 'OverwriteType', true);
}

const userOrRole = guild.roles.cache.get(overwrite.id) ?? guild.client.users.cache.get(overwrite.id);
if (!userOrRole) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'parameter', 'User nor a Role');
const type = userOrRole instanceof Role ? OverwriteType.Role : OverwriteType.Member;
let type;
if (typeof overwrite.id === 'string') {
if (overwrite.type === undefined) {
throw new DiscordjsTypeError(ErrorCodes.PermissionOverwritesTypeMandatory);
}
type = overwrite.type;
} else {
type = overwrite.id instanceof Role ? OverwriteType.Role : OverwriteType.Member;
if (overwrite.type !== undefined && type !== overwrite.type) {
throw new DiscordjsTypeError(ErrorCodes.PermissionOverwritesTypeMismatch, OverwriteType[type]);
}
}

return {
id: userOrRole.id,
id,
type,
allow: PermissionsBitField.resolve(overwrite.allow ?? PermissionsBitField.DefaultBit).toString(),
deny: PermissionsBitField.resolve(overwrite.deny ?? PermissionsBitField.DefaultBit).toString(),
Expand Down
12 changes: 11 additions & 1 deletion packages/discord.js/typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6519,13 +6519,23 @@ export interface MultipleShardSpawnOptions {
timeout?: number;
}

export interface OverwriteData {
export interface BaseOverwriteData {
allow?: PermissionResolvable;
deny?: PermissionResolvable;
id: GuildMemberResolvable | RoleResolvable;
type?: OverwriteType;
}

export interface OverwriteDataWithMandatoryType extends BaseOverwriteData {
type: OverwriteType;
}

export interface OverwriteDataWithOptionalType extends BaseOverwriteData {
id: Exclude<GuildMemberResolvable | RoleResolvable, Snowflake>;
}

export type OverwriteData = OverwriteDataWithMandatoryType | OverwriteDataWithOptionalType;

export type OverwriteResolvable = PermissionOverwrites | OverwriteData;

export type PermissionFlags = Record<keyof typeof PermissionFlagsBits, bigint>;
Expand Down

0 comments on commit bacc08b

Please sign in to comment.