@@ -85,6 +85,81 @@ export class GuildMember extends Structure {
8585 return this . client . users . get ( this . id ) ?? null ;
8686 }
8787
88+ /**
89+ * The calculated permissions from the member's {@link GuildMemberRoleStore roles}.
90+ * @since 0.0.1
91+ */
92+ public get permissions ( ) : Readonly < Permissions > {
93+ if ( this . id === this . guild . ownerID ) return new Permissions ( Permissions . ALL ) . freeze ( ) ;
94+
95+ const permissions = new Permissions ( this . roles . map ( role => role . permissions ) ) ;
96+ return ( permissions . has ( Permissions . FLAGS . ADMINISTRATOR ) ? permissions . add ( Permissions . ALL ) : permissions ) . freeze ( ) ;
97+ }
98+
99+ /**
100+ * Whether or not the {@link ClientUser client user} can kick this member.
101+ * @since 0.0.1
102+ * @returns `null` when the {@link ClientUser client user}'s member is not cached (or when {@link Client#user} is null),
103+ * or a boolean specifying whether or not the conditions are met.
104+ */
105+ public get kickable ( ) : boolean | null {
106+ return ( this . id !== this . client . user ?. id && this . _manageable && ( this . guild . me as GuildMember ) . permissions . has ( Permissions . FLAGS . KICK_MEMBERS ) ) ?? null ;
107+ }
108+
109+ /**
110+ * Whether or not the {@link ClientUser client user} can ban this member.
111+ * @since 0.0.1
112+ * @returns `null` when the {@link ClientUser client user}'s member is not cached (or when {@link Client#user} is null),
113+ * or a boolean specifying whether or not the conditions are met.
114+ */
115+ public get bannable ( ) : boolean | null {
116+ return ( this . id !== this . client . user ?. id && this . _manageable && ( this . guild . me as GuildMember ) . permissions . has ( Permissions . FLAGS . BAN_MEMBERS ) ) ?? null ;
117+ }
118+
119+ /**
120+ * Whether or not the {@link ClientUser client user} can manage the member's nickname.
121+ * @since 0.0.1
122+ * @returns `null` when the {@link ClientUser client user}'s member is not cached (or when {@link Client#user} is null),
123+ * or a boolean specifying whether or not the conditions are met.
124+ */
125+ public get manageNicknames ( ) : boolean | null {
126+ return ( this . _manageable && ( this . guild . me as GuildMember ) . permissions . has ( Permissions . FLAGS . MANAGE_NICKNAMES ) ) ?? null ;
127+ }
128+
129+ /**
130+ * Whether or not the {@link ClientUser client user} can manage the member's roles.
131+ * @since 0.0.1
132+ * @returns `null` when the {@link ClientUser client user}'s member is not cached (or when {@link Client#user} is null),
133+ * or a boolean specifying whether or not the conditions are met.
134+ */
135+ public get manageRoles ( ) : boolean | null {
136+ return ( this . _manageable && ( this . guild . me as GuildMember ) . permissions . has ( Permissions . FLAGS . MANAGE_ROLES ) ) ?? null ;
137+ }
138+
139+ /**
140+ * Whether or not the {@link ClientUser client user} can manage this member. This is based on:
141+ * - The member is not the {@link Guild#owner guild owner}.
142+ * - The {@link ClientUser client user} is the owner of the {@link Guild}.
143+ * - The {@link ClientUser client user}'s {@link GuildMemberRoleStore#highest highest role} is higher than the member's.
144+ * @since 0.0.1
145+ * @returns `true` when any of the conditions are met, `null` when the {@link ClientUser client user}'s member is not
146+ * cached (or when {@link Client#user} is null), or `false` otherwise.
147+ */
148+ protected get _manageable ( ) : boolean | null {
149+ // If the client user's member instance is not cached, return null.
150+ const { me } = this . guild ;
151+ if ( ! this . client . user || ! me ) return null ;
152+
153+ // If the client is the owner, then it can manage itself
154+ if ( this . guild . ownerID === this . client . user . id ) return true ;
155+
156+ // If this is the owner (and we have already determined we are not the owner), then it can't manage
157+ if ( this . id === this . guild . ownerID ) return false ;
158+
159+ // If the clients highest role is higher than this roles highest role
160+ return me . roles . highest > this . roles . highest ;
161+ }
162+
88163 /**
89164 * Modifies the settings for the member.
90165 * @param data The settings to be set.
@@ -101,11 +176,9 @@ export class GuildMember extends Structure {
101176 * @param channel The channel to check permissions in
102177 */
103178 public permissionsIn ( channel : GuildChannel ) : Readonly < Permissions > {
104- if ( this . id === this . guild . ownerID ) return new Permissions ( Permissions . ALL ) . freeze ( ) ;
105-
106- const permissions = new Permissions ( this . roles . map ( role => role . permissions ) ) ;
179+ const { permissions } = this ;
107180
108- if ( permissions . has ( Permissions . FLAGS . ADMINISTRATOR ) ) return new Permissions ( Permissions . ALL ) . freeze ( ) ;
181+ if ( permissions . equals ( Permissions . ALL ) ) return permissions ;
109182
110183 const overwrites = channel . permissionOverwrites . for ( this ) ;
111184
0 commit comments