Мой отредактированный кулдаун на discord.py не работает

Я попытался изменить библиотеку (core.py) и изменил команду перезарядки на это, чтобы все команды имели 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), но потом люди остыли из-за только одной команды, которую они использовали, вместо всех команд. Как я могу сделать так, чтобы он перезарядился только для пользователя, который использовал команду вместо ВСЕХ, но при этом перезарядить все команды для этого одного пользователя?


person BabyCoder20    schedule 08.09.2019    source источник


Ответы (1)


Похоже, мы должны заставить команды всегда совместно использовать объект CooldownMapping. Это довольно просто, но это означает, что декоратор должен выходить за пределы commanddecorator, поскольку мы больше не можем прикреплять кулдаун к функции и полагаться на механизм command для генерации сопоставления.

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):
    ...
person Patrick Haugh    schedule 08.09.2019