diff --git a/packages/discord.js/src/managers/GuildMemberManager.js b/packages/discord.js/src/managers/GuildMemberManager.js index 6e1ee21bd..5e1ad76b0 100644 --- a/packages/discord.js/src/managers/GuildMemberManager.js +++ b/packages/discord.js/src/managers/GuildMemberManager.js @@ -9,6 +9,7 @@ const { DiscordjsError, DiscordjsTypeError, DiscordjsRangeError, ErrorCodes } = const { BaseGuildVoiceChannel } = require('../structures/BaseGuildVoiceChannel.js'); const { GuildMember } = require('../structures/GuildMember.js'); const { Role } = require('../structures/Role.js'); +const { resolveImage } = require('../util/DataResolver.js'); const { Events } = require('../util/Events.js'); const { GuildMemberFlagsBitField } = require('../util/GuildMemberFlagsBitField.js'); const { Partials } = require('../util/Partials.js'); @@ -358,8 +359,7 @@ class GuildMemberManager extends CachedManager { */ /** - * Edits a member of the guild. - * The user must be a member of the guild + * Edits a member of a guild. * * @param {UserResolvable} user The member to edit * @param {GuildMemberEditOptions} options The options to provide @@ -396,22 +396,44 @@ class GuildMemberManager extends CachedManager { options.flags = GuildMemberFlagsBitField.resolve(options.flags); } - let endpoint; - if (id === this.client.user.id) { - const keys = Object.keys(options); - if (keys.length === 1 && keys[0] === 'nick') endpoint = Routes.guildMember(this.guild.id); - else endpoint = Routes.guildMember(this.guild.id, id); - } else { - endpoint = Routes.guildMember(this.guild.id, id); - } - - const data = await this.client.rest.patch(endpoint, { body: options, reason }); - + const data = await this.client.rest.patch(Routes.guildMember(this.guild.id, id), { body: options, reason }); const clone = this.cache.get(id)?._clone(); clone?._patch(data); return clone ?? this._add(data, false); } + /** + * The data for editing the current application's guild member. + * + * @typedef {Object} GuildMemberEditMeOptions + * @property {?string} [nick] The nickname to set + * @property {?(BufferResolvable|Base64Resolvable)} [banner] The banner to set + * @property {?(BufferResolvable|Base64Resolvable)} [avatar] The avatar to set + * @property {?string} [bio] The bio to set + * @property {string} [reason] The reason to use + */ + + /** + * Edits the current application's guild member in a guild. + * + * @param {GuildMemberEditMeOptions} options The options to provide + * @returns {Promise} + */ + async editMe({ reason, ...options }) { + const data = await this.client.rest.patch(Routes.guildMember(this.guild.id, '@me'), { + body: { + ...options, + banner: options.banner && (await resolveImage(options.banner)), + avatar: options.avatar && (await resolveImage(options.avatar)), + }, + reason, + }); + + const clone = this.me?._clone(); + clone?._patch(data); + return clone ?? this._add(data, false); + } + /** * Options used for pruning guild members. * It's recommended to set {@link GuildPruneMembersOptions#count options.count} diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index ea7b29c80..659389d71 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -4486,6 +4486,7 @@ export class GuildMemberManager extends CachedManager; public edit(user: UserResolvable, options: GuildMemberEditOptions): Promise; + public editMe(options: GuildMemberEditMeOptions): Promise; public fetch( options: FetchMemberOptions | UserResolvable | (FetchMembersOptions & { user: UserResolvable }), ): Promise; @@ -6293,6 +6294,14 @@ export interface GuildMemberEditOptions { roles?: ReadonlyCollection | readonly RoleResolvable[]; } +export interface GuildMemberEditMeOptions { + avatar?: Base64Resolvable | BufferResolvable | null; + banner?: Base64Resolvable | BufferResolvable | null; + bio?: string | null; + nick?: string | null; + reason?: string; +} + export type GuildResolvable = | Guild | GuildEmoji