Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ask for confirmation when banning members with elevated roles #2316

Merged
merged 33 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
50ee6cf
Add safeguard when banning staff
Robin5605 Oct 29, 2022
63c44a4
Update infractions.py
Robin5605 Oct 29, 2022
ff070b5
Fix logical error where user would not get banned
Robin5605 Oct 29, 2022
227a9d7
Update bot/exts/moderation/infraction/infractions.py
Robin5605 Oct 30, 2022
43fc315
Delete view if confirmed
Robin5605 Oct 30, 2022
c636e12
Implement suggestions
Robin5605 Nov 6, 2022
b40f926
Merge branch 'main' into staff-ban-safeguard
Robin5605 Mar 3, 2023
25ed835
Merge branch 'python-discord:main' into staff-ban-safeguard
Robin5605 Mar 3, 2023
ebc5b1a
Use instead of
Robin5605 Mar 3, 2023
2f197d0
Don't call timeout manually
Robin5605 Mar 3, 2023
16bcbb4
Lint
Robin5605 Mar 3, 2023
9b248f1
Switch button colors
Robin5605 Mar 3, 2023
2a92fba
Remove message bind to view class
Robin5605 Mar 3, 2023
d87472c
Merge branch 'main' of https://github.com/Robin5605/pydis-bot into st…
Robin5605 Jun 27, 2023
e6c7172
Set message property of view to sent message
Robin5605 Jun 27, 2023
6031c2e
Merge branch 'main' into staff-ban-safeguard
Robin5605 Jun 27, 2023
c24da99
Update poetry.lock
Robin5605 Jun 27, 2023
f60d322
Remove unnecessary View initializer
Robin5605 Jun 27, 2023
1b3cc22
Merge branch 'staff-ban-safeguard' of https://github.com/Robin5605/py…
Robin5605 Jun 27, 2023
7f02fc0
Send message indicating if the infraction was cancelled or not
Robin5605 Jun 27, 2023
af319fd
Remove feedback on confirm
Robin5605 Jul 10, 2023
dacbff6
Merge branch 'python-discord:main' into staff-ban-safeguard
Robin5605 Jul 10, 2023
587aed3
Merge main into staff-ban-safeguard
Robin5605 Jul 10, 2023
45e7420
Make invocation async
Robin5605 Jul 10, 2023
59868c5
Make .stop() invocation sync again
Robin5605 Jul 10, 2023
5cd5e8b
Clean up code
ichard26 Dec 25, 2023
d0ea572
Merge branch 'main' into staff-ban-safeguard
ichard26 Dec 25, 2023
41dbc24
Avoid truncating early and send message on timeout
ichard26 Mar 12, 2024
2bb25aa
Should probably move this, too
ichard26 Mar 12, 2024
90da4a1
Fail safely
ichard26 Mar 14, 2024
0f7ab89
Move view to a new file
ichard26 Mar 25, 2024
83f7b44
Break out confirmation into its own function
ichard26 Mar 25, 2024
7f56f2d
Merge branch 'main' into staff-ban-safeguard
wookie184 Mar 26, 2024
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
43 changes: 43 additions & 0 deletions bot/exts/moderation/infraction/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import arrow
import discord
from botcore.site_api import ResponseCodeError
from botcore.utils import interactions
from discord import ButtonStyle, Interaction, Message, TextChannel
from discord.ext.commands import Context
from discord.ui import Button

import bot
from bot.constants import Colours, Icons
Expand Down Expand Up @@ -269,3 +272,43 @@ async def send_private_embed(user: MemberOrUser, embed: discord.Embed) -> bool:
"The user either could not be retrieved or probably disabled their DMs."
)
return False


class StaffBanConfirmationView(interactions.ViewWithUserAndRoleCheck):
"""The confirmation view that is sent when a moderator attempts to ban a staff member."""
ichard26 marked this conversation as resolved.
Show resolved Hide resolved

def __init__(
self,
*,
allowed_users: t.Sequence[int],
allowed_roles: t.Sequence[int],
timeout: t.Optional[float] = 180,
message: t.Optional[Message] = None
) -> None:
super().__init__(
allowed_users=allowed_users,
allowed_roles=allowed_roles,
timeout=timeout,
message=message
ChrisLovering marked this conversation as resolved.
Show resolved Hide resolved
)

self.value: t.Optional[bool] = None

async def send(self, channel: TextChannel, *, message_content: str) -> None:
Robin5605 marked this conversation as resolved.
Show resolved Hide resolved
Robin5605 marked this conversation as resolved.
Show resolved Hide resolved
"""Send this view to the given channel with the given message content."""
self.message = await channel.send(message_content, view=self)
Robin5605 marked this conversation as resolved.
Show resolved Hide resolved

@discord.ui.button(label="Confirm", style=ButtonStyle.green)
async def confirm(self, interaction: Interaction, button: Button) -> None:
"""Callback coroutine that is called when the "confirm" button is pressed."""
Robin5605 marked this conversation as resolved.
Show resolved Hide resolved
await interaction.response.defer()
Robin5605 marked this conversation as resolved.
Show resolved Hide resolved
self.value = True
Robin5605 marked this conversation as resolved.
Show resolved Hide resolved
self.stop()

@discord.ui.button(label="Cancel", style=ButtonStyle.red)
async def cancel(self, interaction: Interaction, button: Button) -> None:
"""Callback coroutine that is called when the "cancel" button is pressed."""
await interaction.response.defer()
Robin5605 marked this conversation as resolved.
Show resolved Hide resolved
self.value = False
Robin5605 marked this conversation as resolved.
Show resolved Hide resolved
await super().on_timeout()
self.stop()
47 changes: 41 additions & 6 deletions bot/exts/moderation/infraction/infractions.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,12 +466,6 @@ async def apply_ban(
log.trace("Old tempban is being replaced by new permaban.")
await self.pardon_infraction(ctx, "ban", user, send_msg=is_temporary)

infraction = await _utils.post_infraction(ctx, user, "ban", reason, active=True, **kwargs)
if infraction is None:
return None

infraction["purge"] = "purge " if purge_days else ""

self.mod_log.ignore(Event.member_remove, user.id)

if reason:
Expand All @@ -480,6 +474,47 @@ async def apply_ban(
async def action() -> None:
await ctx.guild.ban(user, reason=reason, delete_message_days=purge_days)

if isinstance(user, Member) and any(role.id in constants.STAFF_PARTNERS_COMMUNITY_ROLES for role in user.roles):
confirmation_view = _utils.StaffBanConfirmationView(
ichard26 marked this conversation as resolved.
Show resolved Hide resolved
allowed_users=(ctx.author.id,),
Robin5605 marked this conversation as resolved.
Show resolved Hide resolved
allowed_roles=constants.MODERATION_ROLES,
timeout=10,
)

await confirmation_view.send(
ctx.channel,
message_content="That user is a Helper. Are you sure you want to ban them?",
Robin5605 marked this conversation as resolved.
Show resolved Hide resolved
)

await confirmation_view.wait()
if confirmation_view.value is None:
log.trace(
"Attempted ban of user %s by moderator %s cancelled due to timeout.",
str(user),
str(ctx.author),
)

return None

elif confirmation_view.value is False:
log.trace(
"Attempted ban of user %s by moderator %s cancelled due to manual cancel.",
str(user),
str(ctx.author),
)

return None

# There are a few ways we could get here:
# The user was not a member, which means they can't be staff
# The user was a member and not staff, so just ban them
# The user was a staff and the ban was confirmed
infraction = await _utils.post_infraction(ctx, user, "ban", reason, active=True, **kwargs)
ichard26 marked this conversation as resolved.
Show resolved Hide resolved
if infraction is None:
return None

infraction["purge"] = "purge " if purge_days else ""

await self.apply_infraction(ctx, infraction, user, action)

bb_cog: t.Optional[BigBrother] = self.bot.get_cog("Big Brother")
Expand Down