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

Support editing of timeout durations. #2839

Merged
merged 5 commits into from
Mar 29, 2024
Merged

Support editing of timeout durations. #2839

merged 5 commits into from
Mar 29, 2024

Conversation

shtlrs
Copy link
Member

@shtlrs shtlrs commented Dec 9, 2023

All of the infractions that we have are scheduled for expiry thanks to our own Scheduler.

However, when it comes to timeouts/mutes, the expiry is handled by Discord itself, and the duration that we set in our databse serves no purposes besides their notifying the user about re-acquiring the ability to send messages again.

So this particular case needs to be handled on its own whenver the infraction type is a timeout and a new expiry datetime has been assigned.

@ichard26 ichard26 added a: moderation Related to community moderation functionality: (moderation, defcon, verification) p: 2 - normal Normal Priority s: needs review Author is waiting for someone to review and approve t: bug Something isn't working labels Dec 9, 2023
@ichard26 ichard26 requested review from ChrisLovering, vivekashok1221 and ichard26 and removed request for jb3, ks129 and Den4200 December 25, 2023 05:06
Copy link
Member

@vivekashok1221 vivekashok1221 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few wrinkles to iron out but code works otherwise.

bot/exts/moderation/infraction/management.py Show resolved Hide resolved
Comment on lines 240 to 239
if user and infraction["type"] == "timeout":
await user.edit(reason=reason, timed_out_until=expiry)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the user is not present in the server, the infraction duration is updated in the database and a confirmation message is sent- but the actual timeout duration is not changed Discord-side (basically the same undesirable behaviour we have for editing timeout duration right now) .

We should either:
a) notify that the user has left the server
b) apply the new timeout duration when the user rejoins the server (might have to bring back some of logic we had for on_member_join event from back when we used @muted role for muting users)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming it's not possible to change timeout duration for users while they are not present in the server.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wookie184 wookie184 added s: waiting for author Waiting for author to address a review or respond to a comment and removed s: needs review Author is waiting for someone to review and approve labels Jan 28, 2024
Comment on lines 660 to 664
if active_timeouts and not member.is_timed_out():
reason = f"Applying active timeout for returning member: {active_timeouts[0]['id']}"

async def action() -> None:
await member.edit(timed_out_until=arrow.get(active_timeouts[0]["expires_at"]).datetime, reason=reason)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the following error when my test account that I muted rejoins the server (while the timeout is still active) because member.is_timed_out() is True and hence reason is not assigned a value:

bot-1        |   File "/bot/bot/exts/moderation/infraction/infractions.py", line 664, in action
bot-1        |     await member.edit(timed_out_until=arrow.get(active_timeouts[0]["expires_at"]).datetime, reason=reason)
bot-1        |                                                                                                    ^^^^^^
bot-1        | NameError: cannot access free variable 'reason' where it is not associated with a value in enclosing scope

Copy link
Member

@vivekashok1221 vivekashok1221 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late review, I was teaching my houseplants Morse code. Please forgive.

reason = f"Applying active timeout for returning member: {active_timeouts[0]['id']}"

async def action() -> None:
await member.edit(timed_out_until=arrow.get(active_timeouts[0]["expires_at"]).datetime, reason=reason)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line triggers an IndexError whenever a user without an active timeout infraction joins the server.

Copy link
Member Author

@shtlrs shtlrs Mar 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good find, this and the NameError were fixed in the force push

Comment on lines 661 to 671
if active_timeouts and not member.is_timed_out():
reason = f"Applying active timeout for returning member: {active_timeouts[0]['id']}"

async def action() -> None:
await member.edit(timed_out_until=arrow.get(active_timeouts[0]["expires_at"]).datetime, reason=reason)
await self.reapply_infraction(active_timeouts[0], action)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this overlook users whose timeout duration was edited while they were not present on the server but are still under a timeout when they rejoin the server? Once they rejoin the server, they will still be under the old timeout duration and not the new edited duration.

Copy link
Member Author

@shtlrs shtlrs Mar 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this look ?

timeout_infraction = active_timeouts[0]
expiry = arrow.get(timeout_infraction["expires_at"], tzinfo=UTC).datetime
if member.is_timed_out():
expiry = max(expiry, member.timed_out_until)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we always use the expiry from the database?
With your current approach, if a moderator reduces the timeout duration, the infraction log will display the new duration. However, when the user rejoins the server, the old (original) longer timeout duration will be applied.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not on a streak this period of the year...

You're right, I'll fix that.

@vivekashok1221
Copy link
Member

vivekashok1221 commented Mar 19, 2024

I've noticed something that could warrant its own issue. When attempting to unmute a user who left the server, the bot will reply that the it has failed to pardon the infraction since the user has left the server. However, it will also mark the infraction as inactive in the db. This means that once the user rejoins, someone will have to manually remove the timeout.

@shtlrs shtlrs force-pushed the allow-mute-edits branch 2 times, most recently from 0c480ec to eba7740 Compare March 19, 2024 23:26
@shtlrs
Copy link
Member Author

shtlrs commented Mar 19, 2024

I've noticed something that could warrant its own issue. When attempting to unmute a user who left the server, the bot will reply that the it has failed to pardon the infraction since the user has left the server. However, it will also mark the infraction as inactive in the db. This means that once the user rejoins, someone will have to manually remove the timeout.

Yes, i think this should be dealt with in a separate issue.

Copy link
Member

@vivekashok1221 vivekashok1221 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🌟 🥇

I do have a minor comment but I'm fine with merging this PR as it is.

bot/exts/moderation/infraction/infractions.py Show resolved Hide resolved
@shtlrs shtlrs removed the s: waiting for author Waiting for author to address a review or respond to a comment label Mar 20, 2024
Copy link
Member

@vivekashok1221 vivekashok1221 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🌟 🥇

Copy link
Member

@MarkKoz MarkKoz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some nits



def cap_timeout_duration(duration: datetime.datetime | relativedelta) -> tuple[bool, datetime.datetime]:
"""Caps the duration of a duration to Discord's limit."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""Caps the duration of a duration to Discord's limit."""
"""Cap a duration to Discord's limit."""



async def notify_timeout_cap(bot: Bot, ctx: Context, user: discord.Member) -> None:
"""Notifies moderators about a timeout duration being capped."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imperative mood is our prevailing style.

Suggested change
"""Notifies moderators about a timeout duration being capped."""
"""Notify moderators about a timeout duration being capped."""

@commands.Cog.listener()
async def on_member_join(self, member: Member) -> None:
"""

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra newline here

Suggested change

if a user isn't a member of the server, trying to edit their timeout will result in an error
If timeout was edited to a longer duration, members could evade being timeout upon rejoining, so we reapply them if that's the case
@shtlrs shtlrs merged commit 972fd18 into main Mar 29, 2024
5 checks passed
@shtlrs shtlrs deleted the allow-mute-edits branch March 29, 2024 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: moderation Related to community moderation functionality: (moderation, defcon, verification) p: 2 - normal Normal Priority t: bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants