diff --git a/packages/core/src/api/guild.ts b/packages/core/src/api/guild.ts index 1963b4b7a153..9cb9f8fdeb03 100644 --- a/packages/core/src/api/guild.ts +++ b/packages/core/src/api/guild.ts @@ -28,6 +28,7 @@ import { type RESTGetAPIGuildPruneCountResult, type RESTGetAPIGuildQuery, type RESTGetAPIGuildResult, + type RESTGetAPIGuildRoleResult, type RESTGetAPIGuildRolesResult, type RESTGetAPIGuildScheduledEventQuery, type RESTGetAPIGuildScheduledEventResult, @@ -397,6 +398,18 @@ export class GuildsAPI { return this.rest.get(Routes.guildRoles(guildId), { signal }) as Promise; } + /** + * Get a role in a guild + * + * @see {@link https://discord.com/developers/docs/resources/guild#get-guild-role} + * @param guildId - The id of the guild to fetch the role from + * @param roleId - The id of the role to fetch + * @param options - The options for fetching the guild role + */ + public async getRole(guildId: Snowflake, roleId: Snowflake, { signal }: Pick = {}) { + return this.rest.get(Routes.guildRole(guildId, roleId), { signal }) as Promise; + } + /** * Creates a guild role * diff --git a/packages/discord.js/src/managers/RoleManager.js b/packages/discord.js/src/managers/RoleManager.js index 5c06613b00d1..a69018f54329 100644 --- a/packages/discord.js/src/managers/RoleManager.js +++ b/packages/discord.js/src/managers/RoleManager.js @@ -2,7 +2,8 @@ const process = require('node:process'); const { Collection } = require('@discordjs/collection'); -const { Routes } = require('discord-api-types/v10'); +const { DiscordAPIError } = require('@discordjs/rest'); +const { RESTJSONErrorCodes, Routes } = require('discord-api-types/v10'); const CachedManager = require('./CachedManager'); const { DiscordjsTypeError, ErrorCodes } = require('../errors'); const { Role } = require('../structures/Role'); @@ -61,16 +62,29 @@ class RoleManager extends CachedManager { * .catch(console.error); */ async fetch(id, { cache = true, force = false } = {}) { - if (id && !force) { + if (!id) { + const data = await this.client.rest.get(Routes.guildRoles(this.guild.id)); + const roles = new Collection(); + for (const role of data) roles.set(role.id, this._add(role, cache)); + return roles; + } + + if (!force) { const existing = this.cache.get(id); if (existing) return existing; } - // We cannot fetch a single role, as of this commit's date, Discord API throws with 405 - const data = await this.client.rest.get(Routes.guildRoles(this.guild.id)); - const roles = new Collection(); - for (const role of data) roles.set(role.id, this._add(role, cache)); - return id ? roles.get(id) ?? null : roles; + try { + const data = await this.client.rest.get(Routes.guildRole(this.guild.id, id)); + return this._add(data, cache); + } catch (error) { + // TODO: Remove this catch in the next major version + if (error instanceof DiscordAPIError && error.code === RESTJSONErrorCodes.UnknownRole) { + return null; + } + + throw error; + } } /**