Nextcord(discord.py分支):如何告知Discord命令正在运行?
问题描述
我用Nextcord(discord.py分支)开发的Discord机器人有个耗时约5秒的命令,若长时间未向Discord服务器返回响应,会被Discord终止上下文,后续发送回复时会触发“Context不存在”的错误。观察到MEE6执行命令时,Discord会显示Sending command...,MEE6还会回复MEE6 is thinking...,但我的机器人无法实现此效果。试过让频道处于输入状态但没用,已知当前ctx是nextcord.interaction.Interaction对象,求实现告知Discord命令正在运行的方法。
最小可复现代码:
import requests, nextcord from nextcord.ext import commands bot = commands.Bot(intents=nextcord.Intents.all()) # 需在Discord开发者门户开启所有意图 @bot.slash_command(name='axolotl') async def axolotl(ctx): # 执行耗时操作 r = requests.get('https://axolotlapi-test.kirondevcoder.repl.co/reddit?nsfw=0', timeout=2) if r.status_code == 200: data = r.json()['data'][0] embed = nextcord.Embed(title='Axolotl !', description=data['text'] or 'No text content.') for media in data['media']: embed.set_image(media) await ctx.send('', embed=embed) else: await ctx.send('', embed=nextcord.Embed(title='Axolotl !', description='调用API时出错了。')) bot.run('你的机器人令牌')
我尝试过的代码(仅命令部分):
@bot.slash_command(name='axolotl') async def axolotl(ctx): async with ctx.channel.typing(): r = requests.get('https://axolotlapi-test.kirondevcoder.repl.co/reddit?nsfw=0', timeout=2) if r.status_code == 200: data = r.json()['data'][0] embed = nextcord.Embed(title='Axolotl !', description=data['text'] or 'No text content.') for media in data['media']: embed.set_image(media) await ctx.send('', embed=embed) else: await ctx.send('', embed=nextcord.Embed(title='Axolotl !', description='调用API时出错了。'))
解决方案
针对Slash Command的Interaction上下文对象,Nextcord提供两种核心方式避免Discord回收上下文:
1. 发送临时初始响应(模拟MEE6的“正在思考”效果)
先发送一条临时消息告知用户机器人正在处理,后续编辑这条消息为最终结果,和MEE6的表现一致:
@bot.slash_command(name='axolotl') async def axolotl(ctx: nextcord.Interaction): # 发送临时提示消息,ephemeral=False让所有人可见,设为True则仅命令发起者可见 await ctx.send("机器人正在思考中...", ephemeral=False) # 改用异步HTTP请求,避免阻塞机器人事件循环 async with nextcord.AsyncWebhookSession() as session: async with session.get('https://axolotlapi-test.kirondevcoder.repl.co/reddit?nsfw=0', timeout=2) as r: if r.status == 200: data = await r.json() data = data['data'][0] embed = nextcord.Embed(title='Axolotl !', description=data['text'] or 'No text content.') for media in data['media']: embed.set_image(media) # 编辑之前的临时消息为最终结果 await ctx.edit(original_message=ctx.last_message, content='', embed=embed) else: await ctx.edit(original_message=ctx.last_message, content='', embed=nextcord.Embed(title='Axolotl !', description='调用API时出错了。'))
2. 使用交互延迟确认机制
向Discord发送延迟确认,告知服务器命令正在处理,可将上下文有效期从默认3秒延长至15分钟,不会显示临时消息,但能避免上下文被回收:
@bot.slash_command(name='axolotl') async def axolotl(ctx: nextcord.Interaction): # 发送延迟确认,延长上下文有效期 await ctx.defer() # 改用异步HTTP请求 async with nextcord.AsyncWebhookSession() as session: async with session.get('https://axolotlapi-test.kirondevcoder.repl.co/reddit?nsfw=0', timeout=2) as r: if r.status == 200: data = await r.json() data = data['data'][0] embed = nextcord.Embed(title='Axolotl !', description=data['text'] or 'No text content.') for media in data['media']: embed.set_image(media) await ctx.send('', embed=embed) else: await ctx.send('', embed=nextcord.Embed(title='Axolotl !', description='调用API时出错了。'))
关键注意事项
ctx.channel.typing()仅对普通消息命令有效,对Slash Command的Interaction上下文无效,这是你之前尝试无效的原因。- 必须把同步的
requests.get换成异步HTTP库(如Nextcord自带的AsyncWebhookSession或aiohttp),否则会阻塞机器人事件循环,导致其他命令无法响应。
内容的提问来源于stack exchange,提问作者HGStyle
相关产品推荐
相关产品推荐

