我的discord.py编辑的冷却时间不起作用

时间:2019-09-08 13:05:32

标签: python python-3.7 discord.py

我尝试更改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),但是后来人们只为使用的一个命令而不是所有命令感到冷静。我该如何使它仅冷却使用该命令的用户而不是所有人,而仍然冷却该用户的所有命令?

1 个答案:

答案 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):
    ...