From d5763f67c91c45ce6fca425eec688d9cb0bdb9f3 Mon Sep 17 00:00:00 2001 From: ValentineGilles <71833334+ValentineGilles@users.noreply.github.com> Date: Sat, 21 Dec 2024 16:21:40 +0100 Subject: [PATCH] fix: giveaways reroll --- background/logs/giveaway.py | 12 +++++++++++- commands/giveaway/commands.py | 34 ++++++++++++++++++++-------------- discord/autocomplete.py | 22 ++++++++++++++++------ 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/background/logs/giveaway.py b/background/logs/giveaway.py index 8416e024..8ee12604 100644 --- a/background/logs/giveaway.py +++ b/background/logs/giveaway.py @@ -197,7 +197,17 @@ async def on_giveaway_end(self, data): # Determine winners winners = [] if participants and winner_count > 0: - winners = choices(participants, weights=weights, k=min(winner_count, len(participants))) + if len(participants) <= winner_count: + # If there are fewer participants than winners, all participants are winners + winners = participants + else: + # Use weighted random sampling to select winners + selected_indices = set() + while len(selected_indices) < winner_count: + sampled = choices(participants, weights=weights, k=1)[0] + if sampled not in selected_indices: + selected_indices.add(sampled) + winners = list(selected_indices) # Format mention text for winners mention_text = ' '.join([f'<@{winner}>' for winner in winners]) if winners else "No winners" diff --git a/commands/giveaway/commands.py b/commands/giveaway/commands.py index 34c76627..b4bf6f55 100644 --- a/commands/giveaway/commands.py +++ b/commands/giveaway/commands.py @@ -7,12 +7,12 @@ import uuid import base64 -from discord.autocomplete import Autocomplete +from discord import autocomplete from utility.discord_utils import check_commands - +from classes.bot import CustomClient class GiveawayCommands(commands.Cog): - def __init__(self, bot): + def __init__(self, bot: CustomClient): self.bot = bot @commands.slash_command(name="giveaway", description="Manage all giveaway-related commands.") @@ -58,21 +58,21 @@ async def giveaway_dashboard(self, ctx: disnake.ApplicationCommandInteraction): @giveaway.sub_command(name="reroll", description="Reroll one or more winners of a giveaway using mentions.") @commands.check_any(commands.has_permissions(manage_guild=True), check_commands()) async def giveaway_reroll( - self, - ctx: disnake.ApplicationCommandInteraction, - giveaway_name: str = commands.Param( - description="The ID of the giveaway to reroll.", - autocomplete=Autocomplete.recent_giveaway_ids - ), - users_to_replace: str = commands.Param(description="Mention the users to replace (@user1 @user2)."), - reason: str = commands.Param(default=None, description="Reason for the reroll (optional).") + self, + ctx: disnake.ApplicationCommandInteraction, + giveaway_name: str = commands.Param( + description="The ID of the giveaway to reroll.", + autocomplete=autocomplete.recent_giveaway_ids + ), + users_to_replace: str = commands.Param(description="Mention the users to replace (@user1 @user2)."), + reason: str = commands.Param(default=None, description="Reason for the reroll (optional).") ): """ Reroll winners of a giveaway by replacing specified users. """ giveaway_id = giveaway_name.split(" | ")[1] # Fetch the giveaway data - giveaway = await self.bot.giveaways.find_one({"_id": giveaway_id}) + giveaway = await self.bot.giveaways.find_one({"_id": giveaway_id, "server_id": ctx.guild.id}) if not giveaway: await ctx.send(f"❌ Giveaway with ID `{giveaway_id}` not found.", ephemeral=True) return @@ -114,8 +114,14 @@ async def giveaway_reroll( weight *= booster["value"] weights.append(weight) - # Select new winners - new_winners = choices(eligible_participants, weights=weights, k=len(user_ids_to_replace)) + # Select new winners without duplicates + new_winners = [] + already_selected = set() + while len(new_winners) < len(user_ids_to_replace): + sampled = choices(eligible_participants, weights=weights, k=1)[0] + if sampled not in already_selected: + new_winners.append(sampled) + already_selected.add(sampled) # Format the announcement old_winner_mentions = ", ".join([f"<@{uid}>" for uid in user_ids_to_replace]) diff --git a/discord/autocomplete.py b/discord/autocomplete.py index ed211a70..da622afa 100644 --- a/discord/autocomplete.py +++ b/discord/autocomplete.py @@ -431,18 +431,28 @@ async def country_names(self, ctx: disnake.ApplicationCommandInteraction, query: async def recent_giveaway_ids(self, ctx: disnake.ApplicationCommandInteraction, query: str): """ - Autocomplete for recently ended giveaway IDs. + Autocomplete for recently ended giveaway IDs, optionally filtered by server_id. """ - # Calculer la date d'il y a une semaine + server_id = ctx.guild_id + + # Calculating the timestamp for one week ago one_week_ago = datetime.now(timezone.utc) - timedelta(days=7) - # Requête pour récupérer les giveaways récents + # Build the search filter based on the server_id and end_time + search_filter = { + "end_time": {"$gte": one_week_ago} + } + + if server_id: + search_filter["server_id"] = int(server_id) + + # Request the recent giveaway data recent_giveaways = await self.bot.giveaways.find( - {"end_time": {"$gte": one_week_ago}}, + search_filter, {"_id": 1, "prize": 1} ).to_list(length=25) - # Construire les suggestions basées sur les données récupérées + # Build a list of suggestions based on the query giveaway_list = [] for giveaway in recent_giveaways: prize = giveaway.get("prize", "Unknown Prize") @@ -450,7 +460,7 @@ async def recent_giveaway_ids(self, ctx: disnake.ApplicationCommandInteraction, if query.lower() in prize.lower(): giveaway_list.append(f"{prize} | {giveaway_id}") - # Retourner jusqu'à 25 suggestions + # Return the first 25 suggestions return giveaway_list[:25] def setup(bot: CustomClient):