discord.py中如何为每个用户的daily命令设置独立每日冷却?
Discord机器人daily命令按用户单独设置每日冷却的实现
方案1:使用discord.py内置用户维度冷却(快速实现滚动24小时冷却)
discord.py自带的冷却装饰器支持按用户独立计算冷却时长,不会出现全局锁的问题,仅需在原有命令基础上新增装饰器和错误处理即可:
from discord.ext import commands import random import json # 保留你原有的open_account、get_bank_data逻辑不变 @client.command() # 冷却规则:每个用户每24小时仅能调用1次 @commands.cooldown(rate=1, per=86400, type=commands.BucketType.user) async def daily(ctx): await open_account(ctx.author) users = await get_bank_data() user = ctx.author earning = random.randrange(101) await ctx.send(f":dollar: Daily wallet has been claimed! You got: **{earning}$**") users[str(user.id)]["wallet"] += earning with open('./bank.json', 'w') as f: json.dump(users,f) # 新增冷却触发的用户提示 @daily.error async def daily_cooldown_handler(ctx, error): if isinstance(error, commands.CommandOnCooldown): remain_time = round(error.retry_after, 1) await ctx.send(f"⏳ 你正在每日奖励冷却期内,请{remain_time}秒后再尝试领取")
注意:该方式的冷却逻辑为滚动24小时,即用户今天10点领取后,要等到明天10点才能再次领取,不是按自然日零点重置。
方案2:自定义自然日冷却(适配现有JSON存储逻辑)
如果需要实现“每日零点自动重置领取资格”的自然日冷却规则,可在原有bank.json的用户数据结构中新增冷却状态字段,逐次调用时校验:
- 改造原有
open_account函数,为所有用户补充冷却状态的默认字段:
import datetime async def open_account(user): users = await get_bank_data() if str(user.id) in users: # 为存量老用户补全新增的冷却字段 if "last_daily_date" not in users[str(user.id)]: users[str(user.id)]["last_daily_date"] = "" return False # 为新用户初始化完整数据结构 users[str(user.id)] = { "wallet": 0, "last_daily_date": "" } with open('./bank.json', 'w') as f: json.dump(users, f) return True
- 改造daily命令,新增领取资格校验逻辑:
@client.command() async def daily(ctx): await open_account(ctx.author) users = await get_bank_data() user = ctx.author user_data = users[str(user.id)] # 获取当前本地时区的日期 current_date = str(datetime.datetime.now().date()) # 校验用户当日是否已领取 if user_data["last_daily_date"] == current_date: # 计算距离次日零点的剩余等待时间 now = datetime.datetime.now() next_day = datetime.datetime.now() + datetime.timedelta(days=1) next_midnight = datetime.datetime.combine(next_day.date(), datetime.time.min) remain_seconds = round((next_midnight - now).total_seconds(), 0) await ctx.send(f"⏳ 你今日已领取过每日奖励,距离下次可领取还有{remain_seconds}秒") return earning = random.randrange(101) await ctx.send(f":dollar: Daily wallet has been claimed! You got: **{earning}$**") # 更新用户资产和领取状态 user_data["wallet"] += earning user_data["last_daily_date"] = current_date with open('./bank.json', 'w') as f: json.dump(users,f)
该方案的优势:所有冷却状态独立存储在对应用户的JSON条目里,完全不会出现跨用户的冷却锁问题,且不需要额外引入第三方存储组件。
内容的提问来源于stack exchange,提问作者Grimm
相关产品推荐
相关产品推荐

