diff --git a/techsupport_bot/commands/duck.py b/techsupport_bot/commands/duck.py index d1562b3b..ee2b86b4 100644 --- a/techsupport_bot/commands/duck.py +++ b/techsupport_bot/commands/duck.py @@ -15,6 +15,7 @@ from botlogging import LogContext, LogLevel from core import auxiliary, cogs, extensionconfig from discord import Color as embed_colors +from discord import app_commands from discord.ext import commands if TYPE_CHECKING: @@ -101,6 +102,7 @@ class DuckHunt(cogs.LoopCog): """Class for the actual duck commands Attributes: + duck_group (app_commands.Group): The group for the /duck commands DUCK_PIC_URL (str): The picture for the duck BEFRIEND_URL (str): The picture for the befriend target KILL_URL (str): The picture for the kill target @@ -108,6 +110,10 @@ class DuckHunt(cogs.LoopCog): CHANNELS_KEY (str): The config item for the channels that the duck hunt should run """ + duck_group: app_commands.Group = app_commands.Group( + name="duck", description="...", extras={"module": "duck"} + ) + DUCK_PIC_URL: str = ( "https://www.iconarchive.com/download/i107380/google/" + "noto-emoji-animals-nature/22276-duck.512.png" @@ -126,20 +132,31 @@ async def loop_preconfig(self: Self) -> None: """Preconfig for cooldowns""" self.cooldowns = {} - async def wait(self: Self, config: munch.Munch, _: discord.Guild) -> None: + # "guild_id": datetime + self.next_duck: dict[str, datetime.datetime] = {} + + async def wait(self: Self, config: munch.Munch, guild: discord.Guild) -> None: """Waits a random amount of time before sending another duck This function shouldn't be manually called Args: config (munch.Munch): The guild config to use to determine the min and max wait times + guild (discord.Guild): The guild where the duck is going to appear """ - await asyncio.sleep( - random.randint( - config.extensions.duck.min_wait.value * 3600, - config.extensions.duck.max_wait.value * 3600, - ) + min_wait = config.extensions.duck.min_wait.value * 3600 + max_wait = config.extensions.duck.max_wait.value * 3600 + + fuzzed_min = int(min_wait * random.uniform(0.9, 1.1)) + fuzzed_max = int(max_wait * random.uniform(0.9, 1.1)) + + wait_time = random.randint(fuzzed_min, fuzzed_max) + + self.next_duck[str(guild.id)] = datetime.datetime.now() + datetime.timedelta( + seconds=wait_time ) + await asyncio.sleep(wait_time) + async def execute( self: Self, config: munch.Munch, @@ -169,6 +186,7 @@ async def execute( return self.cooldowns[guild.id] = {} + del self.next_duck[str(guild.id)] embed = discord.Embed( title="*Quack Quack*", @@ -453,6 +471,31 @@ async def get_global_record(self: Self, guild_id: int) -> float: return float(min(speed_records, key=float)) + @app_commands.checks.has_permissions(administrator=True) + @duck_group.command( + name="next", + description="Displays the time for the next duck for this guild", + extras={"module": "duck"}, + ) + async def lookup_next_duck(self: Self, interaction: discord.Interaction) -> None: + """A simple command to show an admin when the next duck will be spawning + + Args: + interaction (discord.Interaction): The interaction that called this command + """ + if str(interaction.guild.id) not in self.next_duck: + embed = auxiliary.prepare_deny_embed( + "Couldn't find a future duck for this guild." + ) + await interaction.response.send_message(embed=embed, ephemeral=True) + return + + embed = auxiliary.prepare_confirm_embed( + "The next duck in this guild:" + f"" + ) + await interaction.response.send_message(embed=embed, ephemeral=True) + @commands.group( brief="Executes a duck command", description="Executes a duck command",