discord.py中!work命令下多职业差异化冷却时间失效问题求助
问题分析与解决方案
看起来你遇到的冷却失效问题根源很明确——你把discord.py的冷却装饰器用错地方了!让我拆解一下问题,再给你一个可行的修复方案:
为什么冷却完全失效?
- 装饰器只对注册的命令生效:你给
youtuberwork、managerwork这些函数加了@cooldown,但这些函数是被你作为普通函数在work命令里调用的,不是用户通过消息触发的命令。discord.py的@cooldown装饰器只有当用户直接触发对应的命令时才会执行冷却检查,直接调用函数完全绕开了这个逻辑。 - 多余的
@commands.is_owner()限制:这个装饰器会导致只有机器人所有者才能直接调用这些子命令,但你本来就不想让用户直接调用它们,而且直接调用函数时这个检查也不会生效,属于冗余且有潜在问题的设置。 - 无用的
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
相关产品推荐
相关产品推荐

