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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:13:59