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

Discord.py中Barrel计时器取消命令失效问题求助

问题分析与解决方案

你的代码核心问题在于每次命令调用的ctx是全新的实例,在barrels命令里给ctx.task赋值的任务,到barrelsc命令里的ctx对象根本访问不到,自然无法取消计时器。

修正方案

我们需要用一个全局容器(比如字典)来存储活跃的计时器任务,把用户ID作为键,这样跨命令就能找到对应的任务。

完整修正代码

import asyncio
import discord
from discord.ext import commands

client = commands.Bot(command_prefix="!", intents=discord.Intents.all())

# 全局字典存储活跃计时器,键为用户ID,值为对应的asyncio.Task对象
active_barrel_tasks = {}

@client.command()
async def barrels(ctx, member: discord.Member = None):
    target_member = member or ctx.author
    user_id = target_member.id

    # 检查用户是否已有活跃计时器
    if user_id in active_barrel_tasks and not active_barrel_tasks[user_id].done():
        await ctx.send(f"{target_member.mention} 已经有一个正在运行的木桶计时器了!")
        return

    # 创建并存储任务
    async def timer_task():
        await asyncio.sleep(10)
        # 任务完成后从字典移除
        del active_barrel_tasks[user_id]
        await ctx.send(f"{target_member.mention} 木桶快可以领取了!")

    task = asyncio.create_task(timer_task())
    active_barrel_tasks[user_id] = task
    await ctx.send(f"为{target_member.mention}启动木桶计时器!")

@client.command()
async def barrelsc(ctx):
    user_id = ctx.author.id

    if user_id in active_barrel_tasks and not active_barrel_tasks[user_id].done():
        task = active_barrel_tasks[user_id]
        task.cancel()
        del active_barrel_tasks[user_id]
        await ctx.send("木桶计时器已取消!")
    else:
        await ctx.send("没有可取消的木桶计时器!")

# 运行机器人(替换成你的token)
client.run("YOUR_BOT_TOKEN")

关键改进点

  • 使用active_barrel_tasks全局字典存储任务,跨命令共享状态
  • 新增重复启动检查,避免同一用户同时运行多个计时器
  • 任务完成后自动从字典移除,避免内存泄漏
  • 取消任务时同步从字典删除条目,保证状态一致

额外说明

如果需要支持按频道而不是按用户管理计时器,只需要把字典的键换成ctx.channel.id即可,根据你的需求调整。

内容的提问来源于stack exchange,提问作者Clyde Owens

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 16:32:18