Discord.py抽奖gcreate命令无报错但无法发送中奖消息如何解决
问题核心原因
你代码的核心错误出在convert函数的返回值使用逻辑上:
- 你写的
convert函数返回的是供前端展示的人类可读字符串(比如输入5d返回"5 days"),后续代码直接尝试将这种带单位和空格的字符串转int传入asyncio.sleep,会直接抛出ValueError异常 - Discord.py的命令框架默认会吞掉未显式捕获的命令执行异常,只会将异常输出到程序运行控制台,不会在频道中提示,所以你看不到报错,只会觉得后续发奖逻辑没有执行
修复方案
1. 重写convert函数,同时返回总秒数和展示文本
修改convert函数,一方面计算抽奖需要等待的总秒数供sleep使用,另一方面返回展示用的文本供embed渲染:
def convert(time_str): # 单位对应秒数映射 unit_to_sec = {"s": 1, "m": 60, "h": 3600, "d": 86400} # 单位对应展示文本映射 unit_to_display = {"s": "秒", "m": "分钟", "h": "小时", "d": "天"} val = int(time_str[:-1]) unit = time_str[-1].lower() # 校验单位合法性 if unit not in unit_to_sec: raise ValueError("仅支持s/秒、m/分钟、h/小时、d/天作为时间单位") total_seconds = val * unit_to_sec[unit] display_text = f"{val}{unit_to_display[unit]}" return total_seconds, display_text
2. 修改gcreate命令的时间处理逻辑
调用convert后分别使用总秒数和展示文本,删掉无用的3秒sleep(如果是测试用途可以保留):
@client.command() @commands.has_permissions(manage_messages=True) async def gcreate(ctx, time: str, *, prize: str): try: total_seconds, time_display = convert(time) except ValueError as e: await ctx.send(f"时间格式错误:{str(e)},示例正确格式:10s、5m、2h、1d") return embed = discord.Embed(title=prize, description=f"发起者 - {ctx.author.mention} 点击🎉反应参与!剩余时间:**{time_display}**", colour = discord.Colour.purple()) msg = await ctx.channel.send(content="🎉 **抽奖活动** 🎉", embed=embed) await msg.add_reaction("🎉") # 等待抽奖结束 await asyncio.sleep(total_seconds) new_msg = await ctx.channel.fetch_message(msg.id) # 获取参与用户列表,排除bot自身 user_list = [user for user in await new_msg.reactions[0].users().flatten() if user != client.user] if len(user_list) == 0: await ctx.send("没有人参与本次抽奖。") else: winner = random.choice(user_list) await ctx.send(f"恭喜 {winner.mention} 赢得了 {prize}!")
额外优化建议
- 超过1小时的抽奖不建议直接用
asyncio.sleep,如果Bot重启、断连,未完成的抽奖任务会直接丢失,建议将抽奖数据存入本地文件/数据库,用定时任务轮询判断抽奖是否到期 - 可以在抽奖过程中定时更新embed的剩余时间,提升使用体验
- 确保Bot拥有频道的「发送消息」「添加反应」「读取消息历史」权限,否则无法正常获取反应用户列表和发送中奖通知
内容的提问来源于stack exchange,提问作者WavyMelon
相关产品推荐
相关产品推荐

