Add cooldown configuration for flag commands (#14)

This commit is contained in:
2025-12-10 13:32:29 +01:00
committed by GitHub
parent 4c05e3d402
commit f261081842
3 changed files with 20 additions and 1 deletions

View File

@@ -65,6 +65,10 @@ Set the following environment variables:
- `FLAGWAVER_HTTP_PORT`: Port for the flagwaver HTTP server (default: `8910`) - `FLAGWAVER_HTTP_PORT`: Port for the flagwaver HTTP server (default: `8910`)
- `UVICORN_HOST`: Host address for the Uvicorn server (default: `0.0.0.0`) - `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`) - `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 ## Installation

View File

@@ -1,11 +1,13 @@
# Copyright (c) Paillat-dev # Copyright (c) Paillat-dev
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, Final
import discord import discord
from discord import ui from discord import ui
from discord.ext.commands import BucketType, cooldown
from config import CONFIG
from renderer.flag import Flag from renderer.flag import Flag
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -14,6 +16,12 @@ if TYPE_CHECKING:
from renderer.base import FlagRenderer from renderer.base import FlagRenderer
from renderer.manager import RendererManager from renderer.manager import RendererManager
COOLDOWN_ARGS: Final = {
"rate": CONFIG.cooldown_rate,
"per": CONFIG.cooldown_per,
"type": BucketType.user,
}
class FlagDisplayView(ui.DesignerView): class FlagDisplayView(ui.DesignerView):
def __init__(self, image: discord.File) -> None: def __init__(self, image: discord.File) -> None:
@@ -36,6 +44,7 @@ class FlaggerCommands(discord.Cog):
await ctx.respond(view=FlagDisplayView(file), files=[file]) await ctx.respond(view=FlagDisplayView(file), files=[file])
@discord.user_command(name="Create a Flag") @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: async def create_flag(self, ctx: discord.ApplicationContext, user: discord.User | discord.Member) -> None:
if user.display_avatar.is_animated(): if user.display_avatar.is_animated():
asset = user.display_avatar.with_format("gif") 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 = discord.SlashCommandGroup("flag", "Commands related to flag rendering.")
@flag.command(name="user", description="Render a user's flag.") @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: async def user(self, ctx: discord.ApplicationContext, user: discord.Member | None = None) -> None:
target = user or ctx.author target = user or ctx.author
if target.display_avatar.is_animated(): if target.display_avatar.is_animated():
@@ -59,6 +69,7 @@ class FlaggerCommands(discord.Cog):
await self.handle_flag_command(ctx, asset.url) await self.handle_flag_command(ctx, asset.url)
@flag.command(name="custom", description="Render a custom flag from an image attachment.") @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: async def custom_flag(self, ctx: discord.ApplicationContext, attachment: discord.Attachment) -> None:
if not attachment.content_type or not attachment.content_type.startswith("image/"): if not attachment.content_type or not attachment.content_type.startswith("image/"):
await ctx.respond("Please provide a valid image attachment.", ephemeral=True) await ctx.respond("Please provide a valid image attachment.", ephemeral=True)

View File

@@ -23,6 +23,8 @@ class Config(BaseModel):
auto_sync_commands: bool = True auto_sync_commands: bool = True
flagwaver_path: Path flagwaver_path: Path
log_level: str = "INFO" log_level: str = "INFO"
cooldown_rate: int
cooldown_per: float
CONFIG = Config( CONFIG = Config(
@@ -34,6 +36,8 @@ CONFIG = Config(
auto_sync_commands=os.getenv("AUTO_SYNC_COMMANDS", "true") == "true", auto_sync_commands=os.getenv("AUTO_SYNC_COMMANDS", "true") == "true",
flagwaver_path=Path(os.getenv("FLAGWAVER_PATH", Path(__file__).parent / "flagwaver" / "dist")), flagwaver_path=Path(os.getenv("FLAGWAVER_PATH", Path(__file__).parent / "flagwaver" / "dist")),
log_level=os.getenv("LOG_LEVEL", "INFO"), 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"] __all__ = ["CONFIG"]