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

discord.py中!work命令下多职业差异化冷却时间失效问题求助

问题分析与解决方案

看起来你遇到的冷却失效问题根源很明确——你把discord.py的冷却装饰器用错地方了!让我拆解一下问题,再给你一个可行的修复方案:

为什么冷却完全失效?

  1. 装饰器只对注册的命令生效:你给youtuberwork、managerwork这些函数加了@cooldown,但这些函数是被你作为普通函数在work命令里调用的,不是用户通过消息触发的命令。discord.py的@cooldown装饰器只有当用户直接触发对应的命令时才会执行冷却检查,直接调用函数完全绕开了这个逻辑。
  2. 多余的@commands.is_owner()限制:这个装饰器会导致只有机器人所有者才能直接调用这些子命令,但你本来就不想让用户直接调用它们,而且直接调用函数时这个检查也不会生效,属于冗余且有潜在问题的设置。
  3. 无用的user参数:你在子命令里定义了user参数,但调用时根本没传值,而且函数内部又重新赋值了user = ctx.author,这本来应该引发参数错误,只是因为你没直接调用这些子命令才没暴露出来。

修复方案:整合逻辑到work命令,手动实现动态冷却

因为不同职业需要不同的冷却时间,静态的@cooldown装饰器满足不了需求,我们可以手动实现冷却逻辑,同时把所有工作逻辑整合到work命令里,让代码更简洁:

修改后的完整代码

import datetime
import json
from discord.ext import commands

# 定义每个职业的冷却时间(秒)和收益
JOB_SETTINGS = {
    "youtuber": {"cooldown": 18000, "earnings": 120},
    "manager": {"cooldown": 19800, "earnings": 150},
    "receptionist": {"cooldown": 16200, "earnings": 100}
}

# 存储用户最后工作的时间(键:用户ID字符串,值:时间戳)
WORK_COOLDOWNS = {}

client = commands.Bot(command_prefix="!", intents=...)  # 记得补充你的intents设置

async def open_account(user):
    # 你的open_account实现,这里保持不变
    pass

async def getbankdata():
    # 你的getbankdata实现,这里保持不变
    with open("mainbank.json", "r") as f:
        return json.load(f)

@client.command(aliases=["Work", "w", "W"])
async def work(ctx):
    await open_account(ctx.author)
    users = await getbankdata()
    user_id = str(ctx.author.id)
    job = users[user_id]["job"]

    # 检查用户是否有职业
    if not job:
        await ctx.send(f"You have no job! Type !jobs for list of jobs and !getjob *jobname* to get a job.")
        return

    # 检查职业是否在配置中
    if job not in JOB_SETTINGS:
        await ctx.send("Oops, that job doesn't exist!")
        return

    job_info = JOB_SETTINGS[job]
    cooldown_seconds = job_info["cooldown"]
    earnings = job_info["earnings"]

    # 检查冷却时间
    current_time = datetime.datetime.now().timestamp()
    last_work_time = WORK_COOLDOWNS.get(user_id, 0)
    time_since_last_work = current_time - last_work_time

    if time_since_last_work < cooldown_seconds:
        # 计算剩余冷却时间并格式化
        remaining_hours = int((cooldown_seconds - time_since_last_work) // 3600)
        remaining_minutes = int(((cooldown_seconds - time_since_last_work) % 3600) // 60)
        remaining_seconds = int((cooldown_seconds - time_since_last_work) % 60)
        await ctx.send(f"Hold on! You need to wait {remaining_hours}h {remaining_minutes}m {remaining_seconds}s before working again.")
        return

    # 执行工作:增加金币
    users[user_id]["wallet"] += earnings
    await ctx.send(f"You worked as a {job.title()} and earned {earnings} coins!")

    # 保存数据到文件
    with open("mainbank.json", "w") as f:
        json.dump(users, f)

    # 更新用户的最后工作时间
    WORK_COOLDOWNS[user_id] = current_time

关键改进点

  • 动态冷却逻辑:用WORK_COOLDOWNS字典跟踪每个用户的最后工作时间,根据其职业对应的冷却时间进行检查,完美实现不同职业不同冷却的需求。
  • 代码整合:把所有工作逻辑集中到work命令里,去掉了冗余的子命令,让代码更易维护。
  • 清晰的配置:用JOB_SETTINGS字典统一管理职业的冷却和收益,后续新增职业只需要在这个字典里添加条目即可,非常方便。

额外提示

  • 如果你担心机器人重启后WORK_COOLDOWNS里的冷却数据丢失,可以考虑把冷却时间也存储到mainbank.json里,每次启动时加载。
  • 记得确保你的open_account函数会给新用户初始化job字段为None或者空字符串,避免出现键不存在的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 13:24:09