diff options
author | 2021-06-30 17:00:47 +0200 | |
---|---|---|
committer | 2021-07-01 01:16:25 +0200 | |
commit | 605768d14d450dd46057c19560599bbbf0d8d597 (patch) | |
tree | d1eebf751f1ed2c56814d344964b97ac893f13c4 | |
parent | Base functionality of tag fetching with groups and in file metadata (diff) |
Move cooldown handling to the Tag class
Instead of the Cog keeping track of cooldowns of all tags, every tag
now handles its own cooldowns which are registered with the `set_cooldown_for`
method.
This change also fixes the bug where cooldowns can only be on cooldown in only
one channel at a time, with invokations in other places cancelling cooldowns.
-rw-r--r-- | bot/exts/info/tags.py | 49 |
1 files changed, 15 insertions, 34 deletions
diff --git a/bot/exts/info/tags.py b/bot/exts/info/tags.py index 3c7b9ea0b..1665275b9 100644 --- a/bot/exts/info/tags.py +++ b/bot/exts/info/tags.py @@ -67,6 +67,7 @@ class Tag: self.content = post.content self.metadata = post.metadata self._restricted_to: set[int] = set(self.metadata.get("restricted_to", ())) + self._cooldowns: dict[discord.TextChannel, float] = {} @property def embed(self) -> Embed: @@ -82,6 +83,14 @@ class Tag: or self._restricted_to & {role.id for role in member.roles} ) + def on_cooldown_in(self, channel: discord.TextChannel) -> bool: + """Check whether the tag is on cooldown in `channel`.""" + return channel in self._cooldowns and self._cooldowns[channel] > time.time() + + def set_cooldown_for(self, channel: discord.TextChannel) -> None: + """Set the tag to be on cooldown in `channel` for `constants.Cooldowns.tags` seconds.""" + self._cooldowns[channel] = time.time() + constants.Cooldowns.tags + def _fuzzy_search(search: str, target: str) -> float: """A simple scoring algorithm based on how many letters are found / total, with order in mind.""" @@ -105,7 +114,6 @@ class Tags(Cog): def __init__(self, bot: Bot): self.bot = bot - self.tag_cooldowns = {} self._tags: dict[TagIdentifier, Tag] = {} self.initialize_tags() @@ -238,42 +246,14 @@ class Tags(Cog): Tags are on cooldowns on a per-tag, per-channel basis. If a tag is on cooldown, display nothing and return True. """ - def _command_on_cooldown(tag_name: str) -> bool: - """ - Check if the command is currently on cooldown, on a per-tag, per-channel basis. - - The cooldown duration is set in constants.py. - """ - now = time.time() - - cooldown_conditions = ( - tag_name - and tag_name in self.tag_cooldowns - and (now - self.tag_cooldowns[tag_name]["time"]) < constants.Cooldowns.tags - and self.tag_cooldowns[tag_name]["channel"] == ctx.channel.id - ) - - if cooldown_conditions: - return True - return False - - if _command_on_cooldown(tag_identifier.name): - time_elapsed = time.time() - self.tag_cooldowns[tag_identifier.name]["time"] - time_left = constants.Cooldowns.tags - time_elapsed - log.info( - f"{ctx.author} tried to get the '{tag_identifier.name}' tag, but the tag is on cooldown. " - f"Cooldown ends in {time_left:.1f} seconds." - ) - return True - if tag_identifier.name is not None: if (tag := self._tags.get(tag_identifier)) is not None and tag.accessible_by(ctx.author): - if ctx.channel.id not in TEST_CHANNELS: - self.tag_cooldowns[tag_identifier.name] = { - "time": time.time(), - "channel": ctx.channel.id - } + + if tag.on_cooldown_in(ctx.channel): + log.debug(f"Tag {str(tag_identifier)!r} is on cooldown.") + return True + tag.set_cooldown_for(ctx.channel) self.bot.stats.incr( f"tags.usages" @@ -295,6 +275,7 @@ class Tags(Cog): str(identifier) for identifier, tag in suggested_tags if tag.accessible_by(ctx.author) + and not tag.on_cooldown_in(ctx.channel) ) await wait_for_deletion( await ctx.send( |