使用discord.py创建抽奖交互时遭遇Unknown Interaction错误
Discord抽奖机器人Unknown Interaction问题解决
问题背景
使用discord.py开发抽奖机器人时,执行/startgive命令创建抽奖,调用create_giveaway异步请求仪表盘API成功创建抽奖,但无法在服务器发送Discord消息,报错Unknown Interaction。尝试过用self.bot.loop.create_task(self.create_giveaway(data))绕过,但需要额外请求获取抽奖列表,觉得不合理。
交互命令startgive代码
@app_commands.command(name="startgive", description="starts a giveaway") @app_commands.describe( duration="duration of the giveaway", winners="number of winners", prize="the prize being given away", ) async def startgive(self, interaction: discord.Interaction, duration: str, winners: int, prize: str): if interaction.user.guild_permissions.administrator: try: if (winners <= 0): await interaction.response.send_message("Type non-negative number of winners!", ephemeral=True) else: created_at = datetime.now() duration = parser.parse(duration) duration = duration + round(created_at.timestamp()) embed = None try: last_id = self.giveaways.pop()['id'] self.id = int(last_id) + 1 except: self.id = 1 btn = GiveawayButton(self, self.id) giveaway = await self.create_giveaway({ 'guild_id': interaction.guild.id, 'prize': prize, 'entries': None, 'winners': None, 'possible_winners': winners, 'duration': str(datetime.fromtimestamp(duration)), 'created_at': str(created_at), 'ended': False, }) giveaway['created_at'] = datetime.fromtimestamp(duration) giveaway['interaction'] = interaction giveaway['entries'] = [] giveaway['winners'] = [] giveaway['btn'] = btn embed = await self.create_embed(giveaway) giveaway['embed'] = embed await interaction.response.send_message(embed=embed, view=btn) self.task_launcher(giveaway, 1) except Exception as e: print(e) await interaction.response.send_message("Invalid time format! (1 minutes/1m)", ephemeral=True) else: await interaction.response.send_message("You don't have permissions to use this.", ephemeral=True)
create_giveaway函数代码
async def create_giveaway(self, data): endpoint = self.url + "/create-giveaway/" async with aiohttp.ClientSession() as session: async with session.post(endpoint, json=data) as r: if r.status == 200: await self.get_giveaways() return await r.json()
问题原因
Discord要求交互必须在3秒内完成响应,如果create_giveaway中的API请求耗时超过3秒,交互会话会被Discord服务器标记为过期,后续调用interaction.response.send_message就会触发Unknown Interaction错误。
解决方案
核心思路:先快速响应Discord交互,再处理API请求和发送抽奖消息。
修改后的startgive代码
@app_commands.command(name="startgive", description="starts a giveaway") @app_commands.describe( duration="duration of the giveaway", winners="number of winners", prize="the prize being given away", ) async def startgive(self, interaction: discord.Interaction, duration: str, winners: int, prize: str): if not interaction.user.guild_permissions.administrator: await interaction.response.send_message("You don't have permissions to use this.", ephemeral=True) return if winners <= 0: await interaction.response.send_message("Type non-negative number of winners!", ephemeral=True) return try: # 先延迟响应,告诉Discord我们正在处理,避免3秒超时 await interaction.response.defer(ephemeral=False) created_at = datetime.now() duration = parser.parse(duration) duration = duration + round(created_at.timestamp()) try: last_id = self.giveaways.pop()['id'] self.id = int(last_id) + 1 except: self.id = 1 btn = GiveawayButton(self, self.id) # 调用API创建抽奖 giveaway = await self.create_giveaway({ 'guild_id': interaction.guild.id, 'prize': prize, 'entries': None, 'winners': None, 'possible_winners': winners, 'duration': str(datetime.fromtimestamp(duration)), 'created_at': str(created_at), 'ended': False, }) giveaway['created_at'] = datetime.fromtimestamp(duration) giveaway['interaction'] = interaction giveaway['entries'] = [] giveaway['winners'] = [] giveaway['btn'] = btn embed = await self.create_embed(giveaway) giveaway['embed'] = embed # 用followup发送最终的抽奖消息 await interaction.followup.send(embed=embed, view=btn) self.task_launcher(giveaway, 1) except Exception as e: print(e) # 如果处理出错,用followup发送错误提示 await interaction.followup.send("Invalid time format! (1 minutes/1m)", ephemeral=True)
关键修改点
- 提前响应交互:使用
await interaction.response.defer(ephemeral=False)告诉Discord机器人正在处理请求,延长交互有效期。 - 改用followup发送消息:处理完API请求后,用
interaction.followup.send()发送最终的抽奖消息,避免过期的交互会话。 - 调整代码结构:把权限和参数校验提前,减少不必要的嵌套逻辑。
这样既不需要用create_task绕过,也能保证交互响应在Discord的超时限制内,同时正常完成API请求和抽奖消息发送。
内容的提问来源于stack exchange,提问作者jakuboldziej
相关产品推荐
相关产品推荐

