Skip to content

Commit

Permalink
Selftimeout (#574)
Browse files Browse the repository at this point in the history
* Add command /selftimeout

* Remove unnecessary ephemeral

* Remove selftimeout cog header

* Remove unnecessary input check

* !!! Breaking change !!! differentiate self and mod timeout

* Remove unused message

* Move selftimeout guildcheck to decorator

* Add default value to timeout_repo isself

* Fix selftimeout: add_timeout is already called from timeout_parse

* fix timeout_parse comment

* Format self_timeout parameters

* Fix typo in timeout_parse comment

* better /selftimeout x /timeout comment description

* Remove unused message

* Add default value for isself in timeout_parse

* Add default value for isself in timeout_perms

* Add newline after parameter in self_timeout

* better guild_id /selftimeout comment description

* Fix self_timeout decorator formatting

* Fix permission check in /selftimeout
  • Loading branch information
viotalJiplk committed May 30, 2023
1 parent 6d95371 commit aa66233
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 13 deletions.
1 change: 1 addition & 0 deletions cogs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ Containing timeout commands and manipulating with timeout.\
- /timeout user
- /timeout remove
- /timeout list
- /selftimeout
**Tasks:**

- refresh_timeout
Expand Down
48 changes: 39 additions & 9 deletions cogs/timeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import utils
from cogs.base import Base
from config import cooldowns
from config.app_config import config
from config.messages import Messages
from permissions import permission_check
Expand Down Expand Up @@ -89,7 +90,7 @@ async def timeout_embed_listing(self, users, title, room, author):
embeds.append(embed)
await room.send(embeds=embeds)

async def timeout_perms(self, inter, user, duration, endtime, reason) -> bool:
async def timeout_perms(self, inter, user, duration, endtime, reason, isself=False) -> bool:
"""Set timeout for user or remove it and save in db"""
try:
await user.timeout(duration=duration, reason=reason)
Expand All @@ -98,15 +99,16 @@ async def timeout_perms(self, inter, user, duration, endtime, reason) -> bool:
else:
# convert to local time and remove timezone info
starttime = inter.created_at.astimezone(tz=utils.get_local_zone()).replace(tzinfo=None)
self.timeout_repo.add_timeout(user.id, inter.author.id, starttime, endtime, reason)
self.timeout_repo.add_timeout(user.id, inter.author.id, starttime, endtime, reason, isself)
return False
except disnake.Forbidden:
self.perms_users.append(user)
return True

async def timeout_parse(self, inter, user, endtime, reason):
async def timeout_parse(self, inter, user, endtime, reason, isself=False):
"""
Parse time argument to timedelta(length) or datetime object
Parse time argument to timedelta(length) or datetime object and
gives user timeout and adds it to db
Decision tree
-------------
Expand All @@ -121,19 +123,20 @@ async def timeout_parse(self, inter, user, endtime, reason):
convert to timedelta
returns
endtime: class datetime
or None in case of insufficient permissions
"""

# convert to local time and remove timezone info
now = inter.created_at.astimezone(tz=utils.get_local_zone()).replace(tzinfo=None)
if "forever" == endtime.lower():
endtime = now.replace(year=now.year+1000)
if await self.timeout_perms(inter, user, timedelta(days=28), endtime, reason):
if await self.timeout_perms(inter, user, timedelta(days=28), endtime, reason, isself):
return

elif endtime in timestamps:
timeout_duration = timedelta(hours=float(timestamps[endtime]))
endtime = now + timeout_duration
if await self.timeout_perms(inter, user, timeout_duration, endtime, reason):
if await self.timeout_perms(inter, user, timeout_duration, endtime, reason, isself):
return

else:
Expand Down Expand Up @@ -173,10 +176,10 @@ async def timeout_parse(self, inter, user, endtime, reason):

# maximum length for timeout is 28 days set by discord
if timeout_duration.days > 28:
if await self.timeout_perms(inter, user, timedelta(days=28), endtime, reason):
if await self.timeout_perms(inter, user, timedelta(days=28), endtime, reason, isself):
return
else:
if await self.timeout_perms(inter, user, timeout_duration, endtime, reason):
if await self.timeout_perms(inter, user, timeout_duration, endtime, reason, isself):
return
return endtime

Expand Down Expand Up @@ -275,17 +278,43 @@ async def remove_timeout(
async def timeout_list(
self,
inter: disnake.ApplicationCommandInteraction,
selftimeout: bool = commands.Param(default=False)
):
"""List all timed out users"""
await self.update_timeout()

users = self.timeout_repo.get_timeout_users()
users = self.timeout_repo.get_timeout_users_filter_self(selftimeout)
if not users:
await inter.send(Messages.timeout_list_none)
return

await self.timeout_embed_listing(users, "Timeout list", inter, inter.author)

@cooldowns.default_cooldown
@commands.slash_command(
name="selftimeout",
description=Messages.self_timeout,
guild_ids=[config.guild_id]
)
async def self_timeout(
self,
inter: disnake.ApplicationCommandInteraction,
endtime: str = commands.Param(
autocomplete=autocomplete_times,
max_length=20, description=Messages.timeout_time
)
):
# Guild_id is used to prevent users from bypassing timeout
# given by moderator and using selftimeout in DMs

await inter.response.defer(ephemeral=True)

if await self.timeout_parse(inter, inter.user, endtime, Messages.self_timeout_reason, True) is None:
await inter.send(content=Messages.timeout_permission.format(user=inter.user))
self.perms_users = []
return
await inter.send(content=Messages.self_timeout_success)

async def update_timeout(self):
"""update all user's timeout in database and on server"""
users = self.timeout_repo.get_timeout_users()
Expand Down Expand Up @@ -341,6 +370,7 @@ async def on_audit_log_entry_create(self, entry):

await self.submod_helper_room.send(embed=embed)

@self_timeout.error
@timeout_user.error
async def timeout_error(self, inter: disnake.ApplicationCommandInteraction, error):
if isinstance(error, commands.BadArgument):
Expand Down
3 changes: 3 additions & 0 deletions config/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,9 @@ class Messages:
timeout_user_brief = "Použij tag uživatele/uživatelů"
timeout_list_none = "Nenalezeny žádné umlčení."
timeout_member_not_found = "{member} Nikoho takového jsem na serveru nenašel. Ujisti se, že jsi uživatele zadal @tagem."
self_timeout = "Dočasně si zakážeš interakce na serveru"
self_timeout_reason = "Sebeumlčení"
self_timeout_success = "Sebeumlčení proběhlo úspěšně"

# TIMEOUT WARS
timeout_wars_user = "Uživatel {user} byl umlčen na {time:.0f} minut."
Expand Down
3 changes: 2 additions & 1 deletion repository/database/timeout.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from sqlalchemy import BigInteger, Column, DateTime, Interval, String
from sqlalchemy import BigInteger, Boolean, Column, DateTime, Interval, String

from repository.database import database

Expand All @@ -12,3 +12,4 @@ class Timeout(database.base):
end = Column(DateTime)
length = Column(Interval)
reason = Column(String)
isself = Column(Boolean)
19 changes: 16 additions & 3 deletions repository/timeout_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,23 @@ def __init__(self):
def get_timeout_users(self) -> List[Timeout]:
return session.query(Timeout).all()

def get_timeout_users_filter_self(self, isself: bool = False) -> List[Timeout]:
return session.query(Timeout).filter(Timeout.isself == isself).all()

def get_timeout_user(self, user_id: int):
return session.query(Timeout).get(user_id)

def add_timeout(self, user_id: int, mod_id: int, start: datetime, end: datetime, reason: str):
def add_timeout(
self,
user_id: int,
mod_id: int,
start: datetime,
end: datetime,
reason: str,
isself: bool = False
):
"""
Add the user and their timeout to the database.
Add the user and their timeout/selftimeout to the database.
Save all datetimes in the database without timezone information.
"""
exists = self.get_timeout_user(user_id)
Expand All @@ -28,6 +39,7 @@ def add_timeout(self, user_id: int, mod_id: int, start: datetime, end: datetime,
exists.end = end
exists.length = end - start
exists.reason = reason
exists.isself = isself
session.commit()
return
try:
Expand All @@ -37,7 +49,8 @@ def add_timeout(self, user_id: int, mod_id: int, start: datetime, end: datetime,
start=start,
end=end,
length=end-start,
reason=reason
reason=reason,
isself=isself
)
session.add(timeout)
session.commit()
Expand Down

0 comments on commit aa66233

Please sign in to comment.