diff --git a/Document/VoiceCall.md b/Document/VoiceCall.md index a75f2ab..1331867 100644 --- a/Document/VoiceCall.md +++ b/Document/VoiceCall.md @@ -443,10 +443,10 @@ class Player extends EventEmitter { 10_000, ); connection.subscribe(this._player); - await this.channel.guild.me.voice + await this.channel.guild.members.me.voice .setSuppressed(false) .catch(async () => { - return await this.channel.guild.me.voice + return await this.channel.guild.members.me.voice .setRequestToSpeak(true); }); } else { diff --git a/src/managers/GuildEmojiManager.js b/src/managers/GuildEmojiManager.js index 74661f2..9195791 100644 --- a/src/managers/GuildEmojiManager.js +++ b/src/managers/GuildEmojiManager.js @@ -156,7 +156,7 @@ class GuildEmojiManager extends BaseGuildEmojiManager { throw new Error('EMOJI_MANAGED'); } - const { me } = this.guild; + const { me } = this.guild.members; if (!me) throw new Error('GUILD_UNCACHED_ME'); if (!me.permissions.has(Permissions.FLAGS.MANAGE_EMOJIS_AND_STICKERS)) { throw new Error('MISSING_MANAGE_EMOJIS_AND_STICKERS_PERMISSION', this.guild); diff --git a/src/managers/GuildMemberManager.js b/src/managers/GuildMemberManager.js index 33d97c1..a029fb5 100644 --- a/src/managers/GuildMemberManager.js +++ b/src/managers/GuildMemberManager.js @@ -9,6 +9,7 @@ const BaseGuildVoiceChannel = require('../structures/BaseGuildVoiceChannel'); const { GuildMember } = require('../structures/GuildMember'); const { Role } = require('../structures/Role'); const { Events, Opcodes } = require('../util/Constants'); +const { PartialTypes } = require('../util/Constants'); const DataResolver = require('../util/DataResolver'); const SnowflakeUtil = require('../util/SnowflakeUtil'); @@ -119,6 +120,20 @@ class GuildMemberManager extends CachedManager { return data instanceof Buffer ? (options.fetchWhenExisting === false ? null : this.fetch(userId)) : this._add(data); } + /** + * The client user as a GuildMember of this guild + * @type {?GuildMember} + * @readonly + */ + get me() { + return ( + this.resolve(this.client.user.id) ?? + (this.client.options.partials.includes(PartialTypes.GUILD_MEMBER) + ? this._add({ user: { id: this.client.user.id } }, true) + : null) + ); + } + /** * Options used to fetch a single member from a guild. * @typedef {BaseFetchOptions} FetchMemberOptions @@ -179,9 +194,9 @@ class GuildMemberManager extends CachedManager { if (!options || (!options?.query && !options?.user)) { // Check Permissions if ( - this.guild.me.permissions.has('KICK_MEMBERS') || - this.guild.me.permissions.has('BAN_MEMBERS') || - this.guild.me.permissions.has('MANAGE_ROLES') + this.guild.members.me.permissions.has('KICK_MEMBERS') || + this.guild.members.me.permissions.has('BAN_MEMBERS') || + this.guild.members.me.permissions.has('MANAGE_ROLES') ) { return this._fetchMany(); } else { @@ -205,6 +220,15 @@ class GuildMemberManager extends CachedManager { return this._fetchMany(options); } + /** + * Fetches the client user as a GuildMember of the guild. + * @param {BaseFetchOptions} [options] The options for fetching the member + * @returns {Promise} + */ + fetchMe(options) { + return this.fetch({ ...options, user: this.client.user.id }); + } + /** * Options used for searching guild members. * @typedef {Object} GuildSearchMembersOptions diff --git a/src/managers/ThreadMemberManager.js b/src/managers/ThreadMemberManager.js index ce6988e..db9e0c5 100644 --- a/src/managers/ThreadMemberManager.js +++ b/src/managers/ThreadMemberManager.js @@ -36,6 +36,24 @@ class ThreadMemberManager extends CachedManager { return member; } + /** + * Fetches the client user as a ThreadMember of the thread. + * @param {BaseFetchOptions} [options] The options for fetching the member + * @returns {Promise} + */ + fetchMe(options) { + return this.fetch(this.client.user.id, options); + } + + /** + * The client user as a ThreadMember of this ThreadChannel + * @type {?ThreadMember} + * @readonly + */ + get me() { + return this.resolve(this.client.user.id); + } + /** * Data that resolves to give a ThreadMember object. This can be: * * A ThreadMember object diff --git a/src/structures/BaseGuildVoiceChannel.js b/src/structures/BaseGuildVoiceChannel.js index 8fe65a1..7caa79d 100644 --- a/src/structures/BaseGuildVoiceChannel.js +++ b/src/structures/BaseGuildVoiceChannel.js @@ -75,7 +75,7 @@ class BaseGuildVoiceChannel extends GuildChannel { if (permissions.has(Permissions.FLAGS.ADMINISTRATOR, false)) return true; return ( - this.guild.me.communicationDisabledUntilTimestamp < Date.now() && + this.guild.members.me.communicationDisabledUntilTimestamp < Date.now() && permissions.has(Permissions.FLAGS.CONNECT, false) ); } diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 973162e..6c21999 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -26,7 +26,6 @@ const VoiceStateManager = require('../managers/VoiceStateManager'); const { ChannelTypes, DefaultMessageNotificationLevels, - PartialTypes, VerificationLevels, ExplicitContentFilterLevels, Status, @@ -41,6 +40,7 @@ const Util = require('../util/Util'); let deprecationEmittedForSetChannelPositions = false; let deprecationEmittedForSetRolePositions = false; let deprecationEmittedForDeleted = false; +let deprecationEmittedForMe = false; /** * @type {WeakSet} @@ -608,15 +608,16 @@ class Guild extends AnonymousGuild { /** * The client user as a GuildMember of this guild. * @type {?GuildMember} + * @deprecated Use {@link GuildMemberManager#me} instead. * @readonly */ get me() { - return ( - this.members.resolve(this.client.user.id) ?? - (this.client.options.partials.includes(PartialTypes.GUILD_MEMBER) - ? this.members._add({ user: { id: this.client.user.id } }, true) - : null) - ); + if (!deprecationEmittedForMe) { + process.emitWarning('Guild#me is deprecated. Use Guild#members#me instead.', 'DeprecationWarning'); + deprecationEmittedForMe = true; + } + + return this.members.me; } /** diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index 2a79609..481d3cf 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -415,7 +415,7 @@ class GuildChannel extends Channel { // This flag allows managing even if timed out if (permissions.has(Permissions.FLAGS.ADMINISTRATOR, false)) return true; - if (this.guild.me.communicationDisabledUntilTimestamp > Date.now()) return false; + if (this.guild.members.me.communicationDisabledUntilTimestamp > Date.now()) return false; const bitfield = VoiceBasedChannelTypes.includes(this.type) ? Permissions.FLAGS.MANAGE_CHANNELS | Permissions.FLAGS.CONNECT diff --git a/src/structures/GuildEmoji.js b/src/structures/GuildEmoji.js index abe2633..bfdb6ef 100644 --- a/src/structures/GuildEmoji.js +++ b/src/structures/GuildEmoji.js @@ -56,7 +56,7 @@ class GuildEmoji extends BaseGuildEmoji { */ get deletable() { if (!this.guild.me) throw new Error('GUILD_UNCACHED_ME'); - return !this.managed && this.guild.me.permissions.has(Permissions.FLAGS.MANAGE_EMOJIS_AND_STICKERS); + return !this.managed && this.guild.members.me.permissions.has(Permissions.FLAGS.MANAGE_EMOJIS_AND_STICKERS); } /** diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js index 45a6445..d9cda12 100644 --- a/src/structures/GuildMember.js +++ b/src/structures/GuildMember.js @@ -334,7 +334,7 @@ class GuildMember extends Base { if (this.user.id === this.client.user.id) return false; if (this.client.user.id === this.guild.ownerId) return true; if (!this.guild.me) throw new Error('GUILD_UNCACHED_ME'); - return this.guild.me.roles.highest.comparePositionTo(this.roles.highest) > 0; + return this.guild.members.me.roles.highest.comparePositionTo(this.roles.highest) > 0; } /** @@ -343,7 +343,7 @@ class GuildMember extends Base { * @readonly */ get kickable() { - return this.manageable && this.guild.me.permissions.has(Permissions.FLAGS.KICK_MEMBERS); + return this.manageable && this.guild.members.me.permissions.has(Permissions.FLAGS.KICK_MEMBERS); } /** @@ -352,7 +352,7 @@ class GuildMember extends Base { * @readonly */ get bannable() { - return this.manageable && this.guild.me.permissions.has(Permissions.FLAGS.BAN_MEMBERS); + return this.manageable && this.guild.members.me.permissions.has(Permissions.FLAGS.BAN_MEMBERS); } /** diff --git a/src/structures/Invite.js b/src/structures/Invite.js index 35e1731..1da4353 100644 --- a/src/structures/Invite.js +++ b/src/structures/Invite.js @@ -245,7 +245,7 @@ class Invite extends Base { if (!guild.me) throw new Error('GUILD_UNCACHED_ME'); return ( this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false) || - guild.me.permissions.has(Permissions.FLAGS.MANAGE_GUILD) + guild.members.me.permissions.has(Permissions.FLAGS.MANAGE_GUILD) ); } diff --git a/src/structures/Message.js b/src/structures/Message.js index db2b2ee..90931d7 100644 --- a/src/structures/Message.js +++ b/src/structures/Message.js @@ -638,7 +638,7 @@ class Message extends Base { return Boolean( this.author.id === this.client.user.id || (permissions.has(Permissions.FLAGS.MANAGE_MESSAGES, false) && - this.guild.me.communicationDisabledUntilTimestamp < Date.now()), + this.guild.members.me.communicationDisabledUntilTimestamp < Date.now()), ); } @@ -1040,7 +1040,7 @@ class Message extends Base { this.mentions.everyone || this.mentions.repliedUser?.id === this.client.user.id || this.mentions.users.has(this.client.user.id) || - (this.guildId && this.mentions.roles.some(r => this.guild.me._roles?.includes(r.id))) + (this.guildId && this.mentions.roles.some(r => this.guild.members.me._roles?.includes(r.id))) ? 1 : 0, }, diff --git a/src/structures/ThreadChannel.js b/src/structures/ThreadChannel.js index 55e7c63..54646cc 100644 --- a/src/structures/ThreadChannel.js +++ b/src/structures/ThreadChannel.js @@ -529,7 +529,7 @@ class ThreadChannel extends Channel { if (permissions.has(Permissions.FLAGS.ADMINISTRATOR, false)) return true; return ( - this.guild.me.communicationDisabledUntilTimestamp < Date.now() && + this.guild.members.me.communicationDisabledUntilTimestamp < Date.now() && permissions.has(Permissions.FLAGS.MANAGE_THREADS, false) ); } @@ -561,7 +561,7 @@ class ThreadChannel extends Channel { !(this.archived && this.locked && !this.manageable) && (this.type !== 'GUILD_PRIVATE_THREAD' || this.joined || this.manageable) && permissions.has(Permissions.FLAGS.SEND_MESSAGES_IN_THREADS, false) && - this.guild.me.communicationDisabledUntilTimestamp < Date.now() + this.guild.members.me.communicationDisabledUntilTimestamp < Date.now() ); } diff --git a/src/structures/VoiceChannel.js b/src/structures/VoiceChannel.js index 6505cdd..b0b95c7 100644 --- a/src/structures/VoiceChannel.js +++ b/src/structures/VoiceChannel.js @@ -120,7 +120,7 @@ class VoiceChannel extends BaseGuildVoiceChannel { if (permissions.has(Permissions.FLAGS.ADMINISTRATOR, false)) return true; return ( - this.guild.me.communicationDisabledUntilTimestamp < Date.now() && permissions.has(Permissions.FLAGS.SPEAK, false) + this.guild.members.me.communicationDisabledUntilTimestamp < Date.now() && permissions.has(Permissions.FLAGS.SPEAK, false) ); } diff --git a/src/structures/VoiceState.js b/src/structures/VoiceState.js index 056d630..ea341e2 100644 --- a/src/structures/VoiceState.js +++ b/src/structures/VoiceState.js @@ -220,10 +220,10 @@ class VoiceState extends Base { * @param {boolean} [request=true] Whether or not the client is requesting to become a speaker. * @example * // Making the client request to speak in a stage channel (raise its hand) - * guild.me.voice.setRequestToSpeak(true); + * guild.members.me.voice.setRequestToSpeak(true); * @example * // Making the client cancel a request to speak - * guild.me.voice.setRequestToSpeak(false); + * guild.members.me.voice.setRequestToSpeak(false); * @returns {Promise} */ async setRequestToSpeak(request = true) { @@ -246,10 +246,10 @@ class VoiceState extends Base { * @param {boolean} [suppressed=true] Whether or not the user should be suppressed. * @example * // Making the client a speaker - * guild.me.voice.setSuppressed(false); + * guild.members.me.voice.setSuppressed(false); * @example * // Making the client an audience member - * guild.me.voice.setSuppressed(true); + * guild.members.me.voice.setSuppressed(true); * @example * // Inviting another user to speak * voiceState.setSuppressed(false); diff --git a/typings/index.d.ts b/typings/index.d.ts index 9f10cfa..4363278 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1322,6 +1322,7 @@ export class Guild extends AnonymousGuild { public maximumPresences: number | null; public maxStageVideoChannelUsers: number | null; public maxVideoChannelUsers: number | null; + /** @deprecated Use {@link GuildMemberManager.me} instead. */ public readonly me: GuildMember | null; public memberCount: number; public members: GuildMemberManager; @@ -3935,6 +3936,7 @@ export interface BruteforceOptions { export class GuildMemberManager extends CachedManager { private constructor(guild: Guild, iterable?: Iterable); public guild: Guild; + public readonly me: GuildMember | null; public add( user: UserResolvable, options: AddGuildMemberOptions & { fetchWhenExisting: false }, @@ -3954,6 +3956,7 @@ export class GuildMemberManager extends CachedManager>; public fetchBruteforce(options?: BruteforceOptions): Promise>; + public fetchMe(options?: BaseFetchOptions): Promise; public kick(user: UserResolvable, reason?: string): Promise; public list(options?: GuildListMembersOptions): Promise>; public prune(options: GuildPruneMembersOptions & { dry?: false; count: false }): Promise; @@ -4182,10 +4185,12 @@ export class ThreadManager extends CachedManager { private constructor(thread: ThreadChannel, iterable?: Iterable); public thread: ThreadChannel; + public readonly me: ThreadMember | null; public add(member: UserResolvable | '@me', reason?: string): Promise; public fetch(member?: UserResolvable, options?: BaseFetchOptions): Promise; /** @deprecated Use `fetch(member, options)` instead. */ public fetch(cache?: boolean): Promise>; + public fetchMe(options?: BaseFetchOptions): Promise; public remove(id: Snowflake | '@me', reason?: string): Promise; }