feat(bot): ✨ Make ban durations stack.

This commit is contained in:
Nyeki.py
2024-10-18 04:38:00 -03:00
parent dc0aadc8f4
commit fa07c6b2e9
5 changed files with 44 additions and 10 deletions
+20 -3
View File
@@ -1,6 +1,6 @@
from typing import Literal from typing import Literal
from datetime import datetime, timezone from datetime import datetime, timezone, timedelta
import discord import discord
from discord import abc from discord import abc
@@ -147,7 +147,7 @@ class Payphone(commands.AutoShardedBot):
async def ban( async def ban(
self, self,
user: discord.User | discord.Member | models.User | int, user: discord.User | discord.Member | models.User | int,
until: datetime | None, duration: timedelta | None,
reason: str, reason: str,
moderator: discord.User | discord.Member | models.User | int | None = None, moderator: discord.User | discord.Member | models.User | int | None = None,
) -> models.Ban: ) -> models.Ban:
@@ -155,7 +155,7 @@ class Payphone(commands.AutoShardedBot):
Args: Args:
user (discord.User | discord.Member | models.User | int): The user to ban or their ID. user (discord.User | discord.Member | models.User | int): The user to ban or their ID.
until (datetime | None): The expiry date, or None if it does not expire. duration (timedelta | None): The expiry date, or None if it does not expire.
reason (str): The reason of the ban. reason (str): The reason of the ban.
moderator (discord.User | discord.Member | models.User | int | None, optional): The moderator (discord.User | discord.Member | models.User | int | None, optional): The
moderator who performed the action. moderator who performed the action.
@@ -173,6 +173,23 @@ class Payphone(commands.AutoShardedBot):
else moderator else moderator
) )
until = datetime.now(timezone.utc) + duration if duration is not None else None
if duration is not None:
last_ban = (
await models.Ban.filter(user_id=user_id)
.order_by("-created_at")
.limit(1)
.first()
)
if last_ban is not None:
until = (
duration + last_ban.expires_at
if last_ban.expires_at is not None
else None
)
row = await models.Ban.create( row = await models.Ban.create(
user_id=user_id, user_id=user_id,
reason=reason, reason=reason,
+7 -4
View File
@@ -31,7 +31,7 @@ class Mods(base.Cog):
self, self,
ctx: commands.Context, ctx: commands.Context,
user: converters.DiscordUserID, user: converters.DiscordUserID,
time: converters.Timedelta | None = None, duration: converters.Timedelta | None = None,
*, *,
reason: str | None = "", reason: str | None = "",
) -> None: ) -> None:
@@ -40,7 +40,7 @@ class Mods(base.Cog):
Options: Options:
- `<user>`: The user to ban or their ID. - `<user>`: The user to ban or their ID.
- `[<time>]`: The amount of time to ban the user for. For example, `1d 5h`. - `[<duration>]`: The amount of time to ban the user for. For example, `1d 5h`.
- `[<reason>]`: The reason of their ban. - `[<reason>]`: The reason of their ban.
""" """
@@ -50,7 +50,7 @@ class Mods(base.Cog):
row = await self.bot.ban( row = await self.bot.ban(
user_id, user_id,
(datetime.now(timezone.utc) + time) if time is not None else None, duration,
reason, reason,
ctx.author, ctx.author,
) )
@@ -58,7 +58,10 @@ class Mods(base.Cog):
message = f"✅ {f"**{profile.name}**" if profile is not None else f"`ID: {user_id}`"} was banned" message = f"✅ {f"**{profile.name}**" if profile is not None else f"`ID: {user_id}`"} was banned"
if row.expires_at: if row.expires_at:
message += f" until <t:{int(row.expires_at.timestamp())}:F> (<t:{int(row.expires_at.timestamp())}:R>)" message += f"{f" for `{fmt.time_to_text(duration)}`" if duration is not None else ""} until <t:{int(row.expires_at.timestamp())}:F> (<t:{int(row.expires_at.timestamp())}:R>)"
else:
message += " permanently"
message += "." message += "."
+5 -2
View File
@@ -98,7 +98,7 @@ class BanUserModal(discord.ui.Modal):
ban = await self.bot.ban( ban = await self.bot.ban(
self.profile.user_id, self.profile.user_id,
datetime.now(timezone.utc) + duration if duration is not None else None, duration,
self.children[0].value, self.children[0].value,
interaction.user.id, interaction.user.id,
) )
@@ -120,7 +120,10 @@ class BanUserModal(discord.ui.Modal):
message = f"✅ **{self.profile.name}** (User ID: {self.profile.user_id}) was banned by {interaction.user.mention}" message = f"✅ **{self.profile.name}** (User ID: {self.profile.user_id}) was banned by {interaction.user.mention}"
if ban.expires_at is not None: if ban.expires_at is not None:
message += f" until <t:{int(ban.expires_at.timestamp())}:F> (<t:{int(ban.expires_at.timestamp())}:R>)" message += f"{f" for `{formatting.time_to_text(duration)}`" if duration is not None else ""} until <t:{int(ban.expires_at.timestamp())}:F> (<t:{int(ban.expires_at.timestamp())}:R>)"
else:
message += " permanently"
message += "." message += "."
@@ -0,0 +1,11 @@
from tortoise import BaseDBAsyncClient
async def upgrade(db: BaseDBAsyncClient) -> str:
return """
CREATE INDEX "idx_ban_created_490013" ON "ban" ("created_at");"""
async def downgrade(db: BaseDBAsyncClient) -> str:
return """
DROP INDEX "idx_ban_created_490013";"""
+1 -1
View File
@@ -346,7 +346,7 @@ class Ban(models.Model):
banned_by: fields.ForeignKeyRelation["User"] = fields.ForeignKeyField( banned_by: fields.ForeignKeyRelation["User"] = fields.ForeignKeyField(
"models.User", related_name="bans_created", null=True "models.User", related_name="bans_created", null=True
) )
created_at: datetime = fields.DatetimeField(auto_now_add=True) created_at: datetime = fields.DatetimeField(auto_now_add=True, db_index=True)
expires_at: datetime | None = fields.DatetimeField(null=True) expires_at: datetime | None = fields.DatetimeField(null=True)
class Meta: class Meta: