You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 04:47:01