discord.py实现giveaway抽奖命令重复中奖者问题如何解决
问题原因
你现在的代码逻辑存在两个导致重复中奖的问题:
- 每次循环挑选中奖者时,都重新拉取完整的反应用户列表,没有移除已经被选中的用户
- 每次都从全量用户池里随机选择,自然可能重复抽到同一个人
修改方案
你只需要调整中奖者选择的逻辑,一次性拉取用户池后用random.sample挑选不重复的用户即可,同时可以补充参与人数不足的异常处理,避免运行报错。
完整修改后的代码
@bot.command() @commands.has_permissions(administrator=True) async def gstart(ctx, time, winners, prize): channel = ctx.channel embed = discord.Embed(title="Giveaway!", description=f"{prize}", color=random.choice(colors)) embed.add_field(name="Hosted by:", value=ctx.author.mention) embed.set_footer(text=f"Ends {time} from now!") my_msg = await ctx.channel.send(embed=embed) await my_msg.add_reaction("🎉") d = time[-1] num = int(time[:-1]) if d == "s": await asyncio.sleep(num) elif d == "m": await asyncio.sleep(num * 60) elif d == "h": await asyncio.sleep(num * 60 * 60) elif d == "d": await asyncio.sleep(num * 60 * 60 * 24) winners_number = int(winners[:-1]) new_msg = await channel.fetch_message(my_msg.id) # 一次性拉取所有参与用户,移除bot users = await new_msg.reactions[0].users().flatten() users.pop(users.index(bot.user)) # 处理参与人数不足的情况 if len(users) < winners_number: await ctx.send(f"参与人数不足,无法选出{winners_number}个中奖者,本次抽奖作废") return # 一次性挑选不重复的中奖者 winners_list = random.sample(users, winners_number) users_mention = [winner.mention for winner in winners_list] await ctx.send(f"Congratulations {', '.join(users_mention)} you won the giveaway !")
额外优化说明
- 把原来的多个
if改成了elif,避免多余的判断 - 新增了参与人数不足的判断,防止
random.sample抛出参数错误 - 最后输出中奖者的时候用
,拼接,格式更美观 - 只拉取一次用户列表,减少API调用,性能更好
内容的提问来源于stack exchange,提问作者RollerController
相关产品推荐
相关产品推荐

