diff --git a/README.md b/README.md index d7acae2..a8d0427 100644 --- a/README.md +++ b/README.md @@ -87,8 +87,8 @@ A structured build plan for developing and deploying the AlphaBot Discord compan --- ### 🔥 Day 4 – Roast Command -- [ ] Build `!roast @user` with AI-generated replies -- [ ] Style roast output with selected personality +- [x] Build `!roast @user` with AI-generated replies +- [x] Style roast output with selected personality - [ ] Add cooldown to prevent spam (optional) --- diff --git a/bot.py b/bot.py index fe6abad..b9bb339 100644 --- a/bot.py +++ b/bot.py @@ -1,9 +1,26 @@ +# bot.py + import os import discord +import yaml from discord.ext import commands from dotenv import load_dotenv from ai import get_ai_response from personality import apply_personality, set_persona +from discord.ext.commands import ( + cooldown, + BucketType, + CooldownMapping, + CommandOnCooldown +) +import yaml + +with open("settings.yml", "r") as f: + settings = yaml.safe_load(f) + +ROAST_COOLDOWN_SECONDS = settings["cooldowns"]["roast"] +GLOBAL_COOLDOWN_SECONDS = settings["cooldowns"]["global"] +COOLDOWN_MSG_TEMPLATE = settings["messages"]["cooldown"] load_dotenv() TOKEN = os.getenv("DISCORD_TOKEN") @@ -14,8 +31,26 @@ intents.message_content = True bot = commands.Bot(command_prefix="!", intents=intents) @bot.event -async def on_ready(): - print(f"✅ Logged in as {bot.user.name}") +async def on_command_error(ctx, error): + if isinstance(error, CommandOnCooldown): + retry_secs = round(error.retry_after, 1) + msg = COOLDOWN_MSG_TEMPLATE.replace("{seconds}", str(retry_secs)) + print("🕒 Chill, mortal. You must wait 11.6s before trying again. 😼") + await ctx.send(msg) + else: + raise error + +# Global cooldown bucket +global_cooldown = CooldownMapping.from_cooldown(1, GLOBAL_COOLDOWN_SECONDS, BucketType.user) + +@bot.check +async def global_command_cooldown(ctx): + bucket = global_cooldown.get_bucket(ctx.message) + retry_after = bucket.update_rate_limit() + + if retry_after: + raise CommandOnCooldown(bucket, retry_after, BucketType.user) + return True @bot.command() async def ping(ctx): @@ -33,5 +68,23 @@ async def setpersona(ctx, *, description): await ctx.send("✅ Persona updated! New style will be used in replies.") +@bot.command(name='roast') +@cooldown(rate=1, per=ROAST_COOLDOWN_SECONDS, type=BucketType.user) +async def roast(ctx): + # Get the mentioned user (or fallback to the author) + target = ctx.message.mentions[0].mention if ctx.message.mentions else ctx.author.mention + + # Build the roast prompt + prompt = f"Roast {target}. Be dramatic, insulting, and sarcastic. Speak in your usual chaotic RGB catgirl personality." + + # Get AI response + response = get_ai_response(prompt) + + # Send the roast back to the channel + await ctx.send(f"😼 {response}") + +@bot.event +async def on_ready(): + print(f"✅ Logged in as {bot.user.name}") bot.run(TOKEN) diff --git a/conda_env.yml b/conda_env.yml index 0eacaef..2fd886b 100644 --- a/conda_env.yml +++ b/conda_env.yml @@ -8,3 +8,4 @@ dependencies: - pip: - discord.py - python-dotenv + - pyyaml diff --git a/requirements.txt b/requirements.txt index c3104a8..b19c107 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ discord.py -python-dotenv \ No newline at end of file +python-dotenv +pyyaml \ No newline at end of file diff --git a/settings.yml b/settings.yml new file mode 100644 index 0000000..224a929 --- /dev/null +++ b/settings.yml @@ -0,0 +1,5 @@ +cooldowns: + global: 15 # seconds between *any* commands from the same user + roast: 60 # seconds +messages: + cooldown: "🕒 Chill, mortal. You must wait {seconds}s before trying again. 😼" \ No newline at end of file