我尝试更改lib(core.py
),并将cooldown命令更改为此,以便所有命令将共享1次冷却时间,例如,在使用!hi
之后,也将!bye
冷却而不仅仅是!hi
:
def shared_cooldown(rate, per, type=BucketType.default):
cooldown = Cooldown(rate, per, type=BucketType.default)
def decorator(func):
if isinstance(func, Command):
func._buckets = CooldownMapping(cooldown)
else:
func.__commands_cooldown__ = cooldown
return func
return decorator
代替此:
def cooldown(rate, per, type=BucketType.default):
"""A decorator that adds a cooldown to a :class:`.Command`
or its subclasses.
A cooldown allows a command to only be used a specific amount
of times in a specific time frame. These cooldowns can be based
either on a per-guild, per-channel, per-user, or global basis.
Denoted by the third argument of ``type`` which must be of enum
type ``BucketType`` which could be either:
- ``BucketType.default`` for a global basis.
- ``BucketType.user`` for a per-user basis.
- ``BucketType.guild`` for a per-guild basis.
- ``BucketType.channel`` for a per-channel basis.
- ``BucketType.member`` for a per-member basis.
- ``BucketType.category`` for a per-category basis.
If a cooldown is triggered, then :exc:`.CommandOnCooldown` is triggered in
:func:`.on_command_error` and the local error handler.
A command can only have a single cooldown.
Parameters
------------
rate: :class:`int`
The number of times a command can be used before triggering a cooldown.
per: :class:`float`
The amount of seconds to wait for a cooldown when it's been triggered.
type: ``BucketType``
The type of cooldown to have.
"""
def decorator(func):
if isinstance(func, Command):
func._buckets = CooldownMapping(Cooldown(rate, per, type))
else:
func.__commands_cooldown__ = Cooldown(rate, per, type)
return func
return decorator
在我的机器人代码中,我添加了以下行:my_cooldown = commands.shared_cooldown(1, 600, commands.shared_cooldown)
和2条命令:
@bot.command(name ="hi")
@my_cooldown
async def hi(ctx):
site = ["https://google.com", "https://youtube.com"]
chosen = random.choice(site)
url = chosen
embed = discord.Embed(title="Your site", description=f"[Click Here]({url})", color=0x00ff00)
if ctx.message.guild == None:
await ctx.author.send('You can not use this command in your DM!')
pass
else:
await ctx.author.send(embed=embed)
@bot.command(name ="bye")
@my_cooldown
async def bye(ctx):
site = ["https://google.com", "https://youtube.com"]
chosen = random.choice(site)
url = chosen
embed = discord.Embed(title="Your site", description=f"[Click Here]({url})", color=0x00ff00)
if ctx.message.guild == None:
await ctx.author.send('You can not use this command in your DM!')
pass
else:
await ctx.author.send(embed=embed)
现在,问题是我的冷却时间适用于所有命令,但是如果一个人使用该命令,则所有用户都会冷却。我尝试将def shared_cooldown(rate, per, type=BucketType.default):
cooldown = Cooldown(rate, per, type=BucketType.default)
更改为def shared_cooldown(rate, per, type=BucketType.user):
cooldown = Cooldown(rate, per, type=BucketType.user)
,但是后来人们只为使用的一个命令而不是所有命令感到冷静。我该如何使它仅冷却使用该命令的用户而不是所有人,而仍然冷却该用户的所有命令?
答案 0 :(得分:0)
似乎我们必须强制命令始终共享CooldownMapping
对象。这很容易,但是这意味着装饰器必须在command
装饰器之外,因为我们不能再将冷却时间附加到函数上了,只能依靠command
机械来生成映射。 / p>
def shared_cooldown(rate, per, type=BucketType.default):
cooldown = Cooldown(rate, per, type=type)
cooldown_mapping = CooldownMapping(cooldown)
def decorator(func):
if isinstance(func, Command):
func._buckets = cooldown_mapping
else:
raise ValueError("Decorator must be applied to command, not the function")
return func
return decorator
这很容易被发现,因为默认存储桶类型将其所有信息存储在冷却时间本身中。粒度更细的存储桶将信息存储在映射中,该映射每次都会重新创建。我在编写原始存储桶时实际上检查了不同的存储桶类型,但是由于只有我一个,所以我没有注意到它实际上每次都在使用默认存储桶。
my_cooldown = shared_cooldown(1, 600, BucketType.User) # Pass the desired bucket type
@my_cooldown # shared cooldown has to go first now
@bot.command(name ="bye")
async def bye(ctx):
...