Skip to content

Commit 76dcaac

Browse files
cheesycodGnomedDev
authored andcommitted
Add PartialGuild::greater_member_hierarchy + member_highest_role (#2856)
1 parent 712d90d commit 76dcaac

File tree

2 files changed

+73
-20
lines changed

2 files changed

+73
-20
lines changed

src/model/guild/mod.rs

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,10 +1222,18 @@ impl Guild {
12221222
/// Returns None if the member has no roles or the member from this guild.
12231223
#[must_use]
12241224
pub fn member_highest_role(&self, member: &Member) -> Option<&Role> {
1225+
Self::_member_highest_role_in(&self.roles, member)
1226+
}
1227+
1228+
/// Helper function that can also be used from [`PartialGuild`].
1229+
pub(crate) fn _member_highest_role_in<'a>(
1230+
roles: &'a ExtractMap<RoleId, Role>,
1231+
member: &Member,
1232+
) -> Option<&'a Role> {
12251233
let mut highest: Option<&Role> = None;
12261234

12271235
for role_id in &member.roles {
1228-
if let Some(role) = self.roles.get(role_id) {
1236+
if let Some(role) = roles.get(role_id) {
12291237
// Skip this role if this role in iteration has:
12301238
// - a position less than the recorded highest
12311239
// - a position equal to the recorded, but a higher ID
@@ -1258,49 +1266,68 @@ impl Guild {
12581266
/// [`position`]: Role::position
12591267
#[must_use]
12601268
pub fn greater_member_hierarchy(&self, lhs_id: UserId, rhs_id: UserId) -> Option<UserId> {
1269+
let lhs = self.members.get(&lhs_id)?;
1270+
let rhs = self.members.get(&rhs_id)?;
1271+
let lhs_highest_role = self.member_highest_role(lhs);
1272+
let rhs_highest_role = self.member_highest_role(rhs);
1273+
1274+
Self::_greater_member_hierarchy_in(
1275+
lhs_highest_role,
1276+
rhs_highest_role,
1277+
self.owner_id,
1278+
lhs,
1279+
rhs,
1280+
)
1281+
}
1282+
1283+
/// Helper function that can also be used from [`PartialGuild`].
1284+
#[must_use]
1285+
pub(crate) fn _greater_member_hierarchy_in(
1286+
lhs_highest_role: Option<&Role>,
1287+
rhs_highest_role: Option<&Role>,
1288+
owner_id: UserId,
1289+
lhs: &Member,
1290+
rhs: &Member,
1291+
) -> Option<UserId> {
12611292
// Check that the IDs are the same. If they are, neither is greater.
1262-
if lhs_id == rhs_id {
1293+
if lhs.user.id == rhs.user.id {
12631294
return None;
12641295
}
12651296

12661297
// Check if either user is the guild owner.
1267-
if lhs_id == self.owner_id {
1268-
return Some(lhs_id);
1269-
} else if rhs_id == self.owner_id {
1270-
return Some(rhs_id);
1298+
if lhs.user.id == owner_id {
1299+
return Some(lhs.user.id);
1300+
} else if rhs.user.id == owner_id {
1301+
return Some(rhs.user.id);
12711302
}
12721303

1273-
let lhs = self
1274-
.member_highest_role(self.members.get(&lhs_id)?)
1275-
.map_or((RoleId::new(1), 0), |r| (r.id, r.position));
1304+
let lhs_role = lhs_highest_role.map_or((RoleId::new(1), 0), |r| (r.id, r.position));
12761305

1277-
let rhs = self
1278-
.member_highest_role(self.members.get(&rhs_id)?)
1279-
.map_or((RoleId::new(1), 0), |r| (r.id, r.position));
1306+
let rhs_role = rhs_highest_role.map_or((RoleId::new(1), 0), |r| (r.id, r.position));
12801307

12811308
// If LHS and RHS both have no top position or have the same role ID, then no one wins.
1282-
if (lhs.1 == 0 && rhs.1 == 0) || (lhs.0 == rhs.0) {
1309+
if (lhs_role.1 == 0 && rhs_role.1 == 0) || (lhs_role.0 == rhs_role.0) {
12831310
return None;
12841311
}
12851312

12861313
// If LHS's top position is higher than RHS, then LHS wins.
1287-
if lhs.1 > rhs.1 {
1288-
return Some(lhs_id);
1314+
if lhs_role.1 > rhs_role.1 {
1315+
return Some(lhs.user.id);
12891316
}
12901317

12911318
// If RHS's top position is higher than LHS, then RHS wins.
1292-
if rhs.1 > lhs.1 {
1293-
return Some(rhs_id);
1319+
if rhs_role.1 > lhs_role.1 {
1320+
return Some(rhs.user.id);
12941321
}
12951322

12961323
// If LHS and RHS both have the same position, but LHS has the lower role ID, then LHS
12971324
// wins.
12981325
//
12991326
// If RHS has the higher role ID, then RHS wins.
1300-
if lhs.1 == rhs.1 && lhs.0 < rhs.0 {
1301-
Some(lhs_id)
1327+
if lhs_role.1 == rhs_role.1 && lhs_role.0 < rhs_role.0 {
1328+
Some(lhs.user.id)
13021329
} else {
1303-
Some(rhs_id)
1330+
Some(rhs.user.id)
13041331
}
13051332
}
13061333

src/model/guild/partial_guild.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,32 @@ impl PartialGuild {
934934
)
935935
}
936936

937+
/// Gets the highest role a [`Member`] of this Guild has.
938+
///
939+
/// Returns None if the member has no roles or the member from this guild.
940+
#[must_use]
941+
pub fn member_highest_role(&self, member: &Member) -> Option<&Role> {
942+
Guild::_member_highest_role_in(&self.roles, member)
943+
}
944+
945+
/// See [`Guild::greater_member_hierarchy`] for more information.
946+
///
947+
/// Note that unlike [`Guild::greater_member_hierarchy`], this method requires a [`Member`] as
948+
/// member data is not available on a [`PartialGuild`].
949+
#[must_use]
950+
pub fn greater_member_hierarchy(&self, lhs: &Member, rhs: &Member) -> Option<UserId> {
951+
let lhs_highest_role = self.member_highest_role(lhs);
952+
let rhs_highest_role = self.member_highest_role(rhs);
953+
954+
Guild::_greater_member_hierarchy_in(
955+
lhs_highest_role,
956+
rhs_highest_role,
957+
self.owner_id,
958+
lhs,
959+
rhs,
960+
)
961+
}
962+
937963
/// Calculate a [`PartialMember`]'s permissions in a given channel in a guild.
938964
///
939965
/// # Panics

0 commit comments

Comments
 (0)