Discord Bot抽奖(Verlosung)命令:有人参与时无中奖通知求助
Discord抽奖命令故障排查:有用户参与时不发送中奖通知
问题描述
我开发了一款带多命令的Discord Bot,其中抽奖命令(!verlosung)在时长结束后无法发送中奖通知:
- 无人参与时,正常显示“参与人数不足”提示;
- 只要有用户参与,完全不发送任何通知;
- 其余功能均正常,仅该抽奖命令从初始阶段就存在问题。
相关代码如下:
import discord import asyncio import random from discord.ext import commands intents = discord.Intents.default() intents.members = True intents.messages = True intents.message_content = True class ValeCraftBot(commands.Bot): winners = 1 # Anzahl der Gewinner festlegen def __init__(self, command_prefix, intents, token): super().__init__(command_prefix=command_prefix, intents=intents) self.token = token bot = ValeCraftBot( command_prefix='!', intents=intents, token= 'BOT_TOKEN') @bot.event async def on_ready(): print(f'{bot.user.name} : Ich bin bereit mein großer Herscher und Meister!') @bot.command(name='umfrage') async def poll(ctx, *, question): embed = discord.Embed( title="---------------", description=f"{question}\n\n:white_check_mark: oder :x:", color=2105893) embed.set_author( name="Wir brauchen deine Meinung!", icon_url= "https://cdn.discordapp.com/attachments/1089918290459115610/1091869819298660472/vprofilbild_-_Kopie.png" ) embed.set_footer( icon_url= "https://cdn.discordapp.com/attachments/1089918290459115610/1091869819298660472/vprofilbild_-_Kopie.png", text="Viel Spaß auf Vale-Craft!") message = await ctx.send(embed=embed) await message.add_reaction("\U00002705") # Emoji-ID für das Häkchen (✅) await message.add_reaction("\U0000274C") # Emoji-ID für das Kreuz (❌) @bot.command(name='verlosung') async def giveaway(ctx, name, duration, winners): embed = discord.Embed( title=name, description=f"Gewinner werden in {duration} Sekunden ausgewählt", color=0xffd700) embed.set_author(name="Verlosung", icon_url=bot.user.avatar.url) message = await ctx.send(embed=embed) await message.add_reaction("🎉") # Reaktion zur Teilnahme hinzufügen def check(reaction, user): return user != bot.user and str( reaction.emoji) == "🎉" and reaction.message.id == message.id try: await bot.wait_for('reaction_add', timeout=int(duration), check=check) except asyncio.TimeoutError: if len(message.reactions) < 1 or message.reactions[0].count < 2: winners_text = "Es gab keine Teilnehmer für die Verlosung." else: participants = await message.reactions[0].users().flatten() bot_user = message.guild.get_member(bot.user.id) if bot_user in participants: participants.remove(bot_user) if len(participants) < 1: winners_text = "Es gab keine Teilnehmer für die Verlosung." else: if len(participants) < int(winners): winners_text = "Es gab nicht genügend Teilnehmer für die Verlosung." else: winner = random.choice(participants) winners_text = f"{winner.mention} hat die Verlosung Gewonnen. Herzlichen Glückwunsch!" winners_embed = discord.Embed(title="Gewinner", description=winners_text, color=0xffd700) winners_embed.set_author(name="Verlosung", icon_url=bot.user.avatar.url) await ctx.send(embed=winners_embed ) # Gewinnerbenachrichtigung im Chat senden @bot.command(name='hilfe') async def help_command(ctx): embed = discord.Embed( title="Vale-Craft Bot Hilfe", description="Hier ist eine Liste der verfügbaren Befehle:", color=0x7289DA) embed.add_field(name="!umfrage <Frage>", value="Erstellt eine Umfrage mit der angegebenen Frage.", inline=False) embed.add_field( name="!verlosung <Name> <Dauer in Sekunden> <Gewinneranzahl>", value= "Startet eine Verlosung mit dem angegebenen Namen, Dauer und der Anzahl der Gewinner.", inline=False) embed.set_footer(text="Viel Spaß mit dem Bot!") await ctx.send(embed=embed) bot.run( 'BOT_TOKEN')
错误原因
核心问题出在wait_for('reaction_add')的逻辑:
- 当有用户参与时,
wait_for会在第一个用户添加反应时立即触发返回,而非等待设定的duration超时; - 此时代码不会进入
asyncio.TimeoutError分支,因此完全不会执行中奖通知的发送逻辑; - 仅当全程无用户添加反应时,才会触发超时,进入通知分支。
修复方案
移除wait_for的监听逻辑,直接等待设定时长后读取当前反应数据即可。修改后的verlosung命令代码如下:
@bot.command(name='verlosung') async def giveaway(ctx, name, duration, winners): embed = discord.Embed( title=name, description=f"Gewinner werden in {duration} Sekunden ausgewählt", color=0xffd700) embed.set_author(name="Verlosung", icon_url=bot.user.avatar.url) message = await ctx.send(embed=embed) await message.add_reaction("🎉") # Reaktion zur Teilnahme hinzufügen # 直接等待设定时长,无需监听反应事件 await asyncio.sleep(int(duration)) # 时长结束后读取反应数据 if len(message.reactions) < 1 or message.reactions[0].count < 2: winners_text = "Es gab keine Teilnehmer für die Verlosung." else: participants = await message.reactions[0].users().flatten() bot_user = message.guild.get_member(bot.user.id) if bot_user in participants: participants.remove(bot_user) if len(participants) < 1: winners_text = "Es gab keine Teilnehmer für die Verlosung." else: if len(participants) < int(winners): winners_text = "Es gab nicht genügend Teilnehmer für die Verlosung." else: # 支持多个获奖者的场景 selected_winners = random.sample(participants, int(winners)) winners_mentions = ", ".join([winner.mention for winner in selected_winners]) winners_text = f"{winners_mentions} {'hat' if int(winners) ==1 else 'haben'} die Verlosung gewonnen. Herzlichen Glückwunsch!" winners_embed = discord.Embed(title="Gewinner", description=winners_text, color=0xffd700) winners_embed.set_author(name="Verlosung", icon_url=bot.user.avatar.url) await ctx.send(embed=winners_embed)
额外优化
- 原代码仅支持单个获奖者,修复后适配
winners参数指定的多个获奖者; - 调整德语语法,多获奖者场景使用正确的动词形式;
- 移除冗余的
check函数和wait_for逻辑,简化代码结构。
内容的提问来源于stack exchange,提问作者FYNN
相关产品推荐
相关产品推荐

