Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion bot/exts/moderation/infraction/infractions.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,10 @@ async def action() -> None:
@respect_role_hierarchy(member_arg=2)
async def apply_kick(self, ctx: Context, user: Member, reason: t.Optional[str], **kwargs) -> None:
"""Apply a kick infraction with kwargs passed to `post_infraction`."""
if user.top_role >= ctx.me.top_role:
await ctx.send(":x: I can't kick users above or equal to me in the role hierarchy.")
return

infraction = await _utils.post_infraction(ctx, user, "kick", reason, active=False, **kwargs)
if infraction is None:
return
Expand All @@ -341,6 +345,10 @@ async def apply_ban(

Will also remove the banned user from the Big Brother watch list if applicable.
"""
if isinstance(user, Member) and user.top_role >= ctx.me.top_role:
await ctx.send(":x: I can't ban users above or equal to me in the role hierarchy.")
return

# In the case of a permanent ban, we don't need get_active_infractions to tell us if one is active
is_temporary = kwargs.get("expires_at") is not None
active_infraction = await _utils.get_active_infraction(ctx, user, "ban", is_temporary)
Expand Down Expand Up @@ -520,7 +528,7 @@ async def cog_check(self, ctx: Context) -> bool:
async def cog_command_error(self, ctx: Context, error: Exception) -> None:
"""Send a notification to the invoking context on a Union failure."""
if isinstance(error, commands.BadUnionArgument):
if discord.User in error.converters or discord.Member in error.converters:
if discord.User in error.converters or Member in error.converters:
await ctx.send(str(error.errors[0]))
error.handled = True

Expand Down
4 changes: 4 additions & 0 deletions bot/exts/moderation/infraction/superstarify.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ async def superstarify(
An optional reason can be provided, which would be added to a message stating their old nickname
and linking to the nickname policy.
"""
if member.top_role >= ctx.me.top_role:
await ctx.send(":x: I can't starify users above or equal to me in the role hierarchy.")
return

if await _utils.get_active_infraction(ctx, member, "superstar"):
return

Expand Down
2 changes: 1 addition & 1 deletion tests/bot/exts/backend/sync/test_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def fake_user(**kwargs):
kwargs.setdefault("id", 43)
kwargs.setdefault("name", "bob the test man")
kwargs.setdefault("discriminator", 1337)
kwargs.setdefault("roles", [666])
kwargs.setdefault("roles", [helpers.MockRole(id=666)])
kwargs.setdefault("in_guild", True)

return kwargs
Expand Down
11 changes: 6 additions & 5 deletions tests/bot/exts/moderation/infraction/test_infractions.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ class TruncationTests(unittest.IsolatedAsyncioTestCase):
"""Tests for ban and kick command reason truncation."""

def setUp(self):
self.me = MockMember(id=7890, roles=[MockRole(id=7890, position=5)])
self.bot = MockBot()
self.cog = Infractions(self.bot)
self.user = MockMember(id=1234, top_role=MockRole(id=3577, position=10))
self.target = MockMember(id=1265, top_role=MockRole(id=9876, position=0))
self.user = MockMember(id=1234, roles=[MockRole(id=3577, position=10)])
self.target = MockMember(id=1265, roles=[MockRole(id=9876, position=1)])
self.guild = MockGuild(id=4567)
self.ctx = MockContext(bot=self.bot, author=self.user, guild=self.guild)
self.ctx = MockContext(me=self.me, bot=self.bot, author=self.user, guild=self.guild)

@patch("bot.exts.moderation.infraction._utils.get_active_infraction")
@patch("bot.exts.moderation.infraction._utils.post_infraction")
Expand Down Expand Up @@ -66,8 +67,8 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):

def setUp(self):
self.bot = MockBot()
self.mod = MockMember(top_role=10)
self.user = MockMember(top_role=1, roles=[MockRole(id=123456)])
self.mod = MockMember(roles=[MockRole(id=7890123, position=10)])
self.user = MockMember(roles=[MockRole(id=123456, position=1)])
self.guild = MockGuild()
self.ctx = MockContext(bot=self.bot, author=self.mod)
self.cog = Infractions(self.bot)
Expand Down
2 changes: 2 additions & 0 deletions tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ def __init__(self, roles: Optional[Iterable[MockRole]] = None, **kwargs) -> None
self.roles = [MockRole(name="@everyone", position=1, id=0)]
if roles:
self.roles.extend(roles)
self.top_role = max(self.roles)

if 'mention' not in kwargs:
self.mention = f"@{self.name}"
Expand Down Expand Up @@ -442,6 +443,7 @@ class MockContext(CustomMockMixin, unittest.mock.MagicMock):

def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)
self.me = kwargs.get('me', MockMember())
self.bot = kwargs.get('bot', MockBot())
self.guild = kwargs.get('guild', MockGuild())
self.author = kwargs.get('author', MockMember())
Expand Down