aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar scragly <[email protected]>2019-01-19 20:54:00 +1000
committerGravatar GitHub <[email protected]>2019-01-19 20:54:00 +1000
commit7692c8b655c0ccdb3c3656dbd122befe263d07fc (patch)
tree0de7c7c886b803f944b945094748bbb978ea92f5
parentMerge branch 'master' into helper-talent-pool (diff)
parentMerge pull request #265 from python-discord/moderation-hierarchy-check (diff)
Merge branch 'master' into helper-talent-pool
-rw-r--r--bot/cogs/moderation.py57
1 files changed, 57 insertions, 0 deletions
diff --git a/bot/cogs/moderation.py b/bot/cogs/moderation.py
index e9acc27b9..6b90d43ab 100644
--- a/bot/cogs/moderation.py
+++ b/bot/cogs/moderation.py
@@ -132,6 +132,11 @@ class Moderation(Scheduler):
**`reason`:** The reason for the kick.
"""
+ if not await self.respect_role_hierarchy(ctx, user, 'kick'):
+ # Ensure ctx author has a higher top role than the target user
+ # Warning is sent to ctx by the helper method
+ return
+
response_object = await post_infraction(ctx, user, type="kick", reason=reason)
if response_object is None:
return
@@ -187,6 +192,12 @@ class Moderation(Scheduler):
**`reason`:** The reason for the ban.
"""
+ member = ctx.guild.get_member(user.id)
+ if not await self.respect_role_hierarchy(ctx, member, 'ban'):
+ # Ensure ctx author has a higher top role than the target user
+ # Warning is sent to ctx by the helper method
+ return
+
response_object = await post_infraction(ctx, user, type="ban", reason=reason)
if response_object is None:
return
@@ -370,6 +381,12 @@ class Moderation(Scheduler):
**`reason`:** The reason for the temporary ban.
"""
+ member = ctx.guild.get_member(user.id)
+ if not await self.respect_role_hierarchy(ctx, member, 'tempban'):
+ # Ensure ctx author has a higher top role than the target user
+ # Warning is sent to ctx by the helper method
+ return
+
response_object = await post_infraction(
ctx, user, type="ban", reason=reason, duration=duration
)
@@ -475,6 +492,11 @@ class Moderation(Scheduler):
**`reason`:** The reason for the kick.
"""
+ if not await self.respect_role_hierarchy(ctx, user, 'shadowkick'):
+ # Ensure ctx author has a higher top role than the target user
+ # Warning is sent to ctx by the helper method
+ return
+
response_object = await post_infraction(ctx, user, type="kick", reason=reason, hidden=True)
if response_object is None:
return
@@ -523,6 +545,12 @@ class Moderation(Scheduler):
**`reason`:** The reason for the ban.
"""
+ member = ctx.guild.get_member(user.id)
+ if not await self.respect_role_hierarchy(ctx, member, 'shadowban'):
+ # Ensure ctx author has a higher top role than the target user
+ # Warning is sent to ctx by the helper method
+ return
+
response_object = await post_infraction(ctx, user, type="ban", reason=reason, hidden=True)
if response_object is None:
return
@@ -662,6 +690,12 @@ class Moderation(Scheduler):
**`reason`:** The reason for the temporary ban.
"""
+ member = ctx.guild.get_member(user.id)
+ if not await self.respect_role_hierarchy(ctx, member, 'shadowtempban'):
+ # Ensure ctx author has a higher top role than the target user
+ # Warning is sent to ctx by the helper method
+ return
+
response_object = await post_infraction(
ctx, user, type="ban", reason=reason, duration=duration, hidden=True
)
@@ -1334,6 +1368,29 @@ class Moderation(Scheduler):
if User in error.converters:
await ctx.send(str(error.errors[0]))
+ async def respect_role_hierarchy(self, ctx: Context, target: Member, infraction_type: str) -> bool:
+ """
+ Check if the highest role of the invoking member is greater than that of the target member
+
+ If this check fails, a warning is sent to the invoking ctx
+
+ Implement as a method rather than a check in order to avoid having to reimplement parameter
+ checks & conversions in a dedicated check decorater
+ """
+
+ actor = ctx.author
+ target_is_lower = target.top_role < actor.top_role
+ if not target_is_lower:
+ log.info(
+ f"{actor} ({actor.id}) attempted to {infraction_type} "
+ f"{target} ({target.id}), who has an equal or higher top role"
+ )
+ await ctx.send(
+ f":x: {actor.mention}, you may not {infraction_type} someone with an equal or higher top role"
+ )
+
+ return target_is_lower
+
def setup(bot):
bot.add_cog(Moderation(bot))