From f2610818420e761a2d1e7ec9ebaacea859ad68f2 Mon Sep 17 00:00:00 2001 From: Paillat Date: Wed, 10 Dec 2025 13:32:29 +0100 Subject: [PATCH] :sparkles: Add cooldown configuration for flag commands (#14) --- README.md | 4 ++++ src/commands/flag_gen.py | 13 ++++++++++++- src/config.py | 4 ++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 15daf1f..5bb01cd 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,10 @@ Set the following environment variables: - `FLAGWAVER_HTTP_PORT`: Port for the flagwaver HTTP server (default: `8910`) - `UVICORN_HOST`: Host address for the Uvicorn server (default: `0.0.0.0`) - `AUTO_SYNC_COMMANDS`: Whether to automatically sync slash commands with Discord (default: `true`) +- `FLAGWAVER_PATH`: Path to the flagwaver distribution directory (default: `src/flagwaver/dist`) +- `LOG_LEVEL`: Logging level for the application (default: `INFO`) +- `COOLDOWN_RATE`: Number of command uses allowed per cooldown period (default: `1`) +- `COOLDOWN_PER`: Cooldown period in seconds (default: `900`, i.e., 15 minutes) ## Installation diff --git a/src/commands/flag_gen.py b/src/commands/flag_gen.py index 9432b06..06e2444 100644 --- a/src/commands/flag_gen.py +++ b/src/commands/flag_gen.py @@ -1,11 +1,13 @@ # Copyright (c) Paillat-dev # SPDX-License-Identifier: MIT -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Final import discord from discord import ui +from discord.ext.commands import BucketType, cooldown +from config import CONFIG from renderer.flag import Flag if TYPE_CHECKING: @@ -14,6 +16,12 @@ if TYPE_CHECKING: from renderer.base import FlagRenderer from renderer.manager import RendererManager +COOLDOWN_ARGS: Final = { + "rate": CONFIG.cooldown_rate, + "per": CONFIG.cooldown_per, + "type": BucketType.user, +} + class FlagDisplayView(ui.DesignerView): def __init__(self, image: discord.File) -> None: @@ -36,6 +44,7 @@ class FlaggerCommands(discord.Cog): await ctx.respond(view=FlagDisplayView(file), files=[file]) @discord.user_command(name="Create a Flag") + @cooldown(**COOLDOWN_ARGS) # ty:ignore[invalid-argument-type] async def create_flag(self, ctx: discord.ApplicationContext, user: discord.User | discord.Member) -> None: if user.display_avatar.is_animated(): asset = user.display_avatar.with_format("gif") @@ -48,6 +57,7 @@ class FlaggerCommands(discord.Cog): flag = discord.SlashCommandGroup("flag", "Commands related to flag rendering.") @flag.command(name="user", description="Render a user's flag.") + @cooldown(**COOLDOWN_ARGS) # ty:ignore[invalid-argument-type] async def user(self, ctx: discord.ApplicationContext, user: discord.Member | None = None) -> None: target = user or ctx.author if target.display_avatar.is_animated(): @@ -59,6 +69,7 @@ class FlaggerCommands(discord.Cog): await self.handle_flag_command(ctx, asset.url) @flag.command(name="custom", description="Render a custom flag from an image attachment.") + @cooldown(**COOLDOWN_ARGS) # ty:ignore[invalid-argument-type] async def custom_flag(self, ctx: discord.ApplicationContext, attachment: discord.Attachment) -> None: if not attachment.content_type or not attachment.content_type.startswith("image/"): await ctx.respond("Please provide a valid image attachment.", ephemeral=True) diff --git a/src/config.py b/src/config.py index d906af2..6d08475 100644 --- a/src/config.py +++ b/src/config.py @@ -23,6 +23,8 @@ class Config(BaseModel): auto_sync_commands: bool = True flagwaver_path: Path log_level: str = "INFO" + cooldown_rate: int + cooldown_per: float CONFIG = Config( @@ -34,6 +36,8 @@ CONFIG = Config( auto_sync_commands=os.getenv("AUTO_SYNC_COMMANDS", "true") == "true", flagwaver_path=Path(os.getenv("FLAGWAVER_PATH", Path(__file__).parent / "flagwaver" / "dist")), log_level=os.getenv("LOG_LEVEL", "INFO"), + cooldown_rate=int(os.getenv("COOLDOWN_RATE", "1")), # 1 per + cooldown_per=float(os.getenv("COOLDOWN_PER", "900")), # 15 minutes ) __all__ = ["CONFIG"]