tux.cogs.services.gif_limiter
¶
Classes:
Name | Description |
---|---|
GifLimiter | This class is a handler for GIF ratelimiting. |
Classes¶
GifLimiter(bot: Tux)
¶
Bases: Cog
This class is a handler for GIF ratelimiting. It keeps a list of GIF send times and routinely removes old times. It will prevent people from posting GIFs if the quotas are exceeded.
Methods:
Name | Description |
---|---|
on_message | Checks for GIFs in every sent message |
old_gif_remover | Regularly cleans old GIF timestamps |
Source code in tux/cogs/services/gif_limiter.py
def __init__(self, bot: Tux) -> None:
self.bot = bot
# Max age for a GIF to be considered a recent post
self.recent_gif_age: int = CONFIG.RECENT_GIF_AGE
# Max number of GIFs sent recently in a channel
self.channelwide_gif_limits: dict[int, int] = CONFIG.GIF_LIMITS_CHANNEL
# Max number of GIFs sent recently by a user to be able to post one in specified channels
self.user_gif_limits: dict[int, int] = CONFIG.GIF_LIMITS
# list of channels in which not to count GIFs
self.gif_limit_exclude: list[int] = CONFIG.GIF_LIMIT_EXCLUDE
# Timestamps for recently-sent GIFs for the server, and channels
# UID, list of timestamps
self.recent_gifs_by_user: defaultdict[int, list[int]] = defaultdict(list)
# Channel ID, list of timestamps
self.recent_gifs_by_channel: defaultdict[int, list[int]] = defaultdict(list)
# Lock to prevent race conditions
self.gif_lock = asyncio.Lock()
self.old_gif_remover.start()
Functions¶
_should_process_message(message: discord.Message) -> bool
async
¶
Checks if a message contains a GIF and was not sent in a blacklisted channel
Parameters:
Name | Type | Description | Default |
---|---|---|---|
message | Message | The message to check. | required |
Returns:
Type | Description |
---|---|
bool | True if the message contains a GIF and was not sent in a blacklisted channel, False otherwise. |
Source code in tux/cogs/services/gif_limiter.py
async def _should_process_message(self, message: discord.Message) -> bool:
"""
Checks if a message contains a GIF and was not sent in a blacklisted channel
Parameters
----------
message : discord.Message
The message to check.
Returns
-------
bool
True if the message contains a GIF and was not sent in a blacklisted channel, False otherwise.
"""
return not (
len(message.embeds) == 0
or "gif" not in message.content.lower()
or message.channel.id in self.gif_limit_exclude
)
_handle_gif_message(message: discord.Message) -> None
async
¶
Checks for ratelimit infringements
Parameters:
Name | Type | Description | Default |
---|---|---|---|
message | Message | The message to check. | required |
Source code in tux/cogs/services/gif_limiter.py
async def _handle_gif_message(self, message: discord.Message) -> None:
"""
Checks for ratelimit infringements
Parameters
----------
message : discord.Message
The message to check.
"""
async with self.gif_lock:
channel: int = message.channel.id
user: int = message.author.id
if (
channel in self.channelwide_gif_limits
and len(self.recent_gifs_by_channel[channel]) >= self.channelwide_gif_limits[channel]
):
await self._delete_message(message, "for channel")
return
if channel in self.user_gif_limits and len(self.recent_gifs_by_user[user]) >= self.user_gif_limits[channel]:
await self._delete_message(message, "for user")
return
# Add message to recent GIFs if it doesn't infringe on ratelimits
current_time: int = int(time())
self.recent_gifs_by_channel[channel].append(current_time)
self.recent_gifs_by_user[user].append(current_time)
_delete_message(message: discord.Message, epilogue: str) -> None
async
¶
Deletes the message passed as an argument, and sends a self-deleting message with the reason
Parameters:
Name | Type | Description | Default |
---|---|---|---|
message | Message | The message to delete. | required |
epilogue | str | The reason for the deletion. | required |
Source code in tux/cogs/services/gif_limiter.py
async def _delete_message(self, message: discord.Message, epilogue: str) -> None:
"""
Deletes the message passed as an argument, and sends a self-deleting message with the reason
Parameters
----------
message : discord.Message
The message to delete.
epilogue : str
The reason for the deletion.
"""
await message.delete()
await message.channel.send(f"-# GIF ratelimit exceeded {epilogue}", delete_after=3)
on_message(message: discord.Message) -> None
async
¶
Checks for GIFs in every sent message
Parameters:
Name | Type | Description | Default |
---|---|---|---|
message | Message | The message to check. | required |
Source code in tux/cogs/services/gif_limiter.py
old_gif_remover() -> None
async
¶
Regularly cleans old GIF timestamps
Parameters:
Name | Type | Description | Default |
---|---|---|---|
self | GifLimiter | The GifLimiter instance. | required |
Source code in tux/cogs/services/gif_limiter.py
@tasks.loop(seconds=20)
async def old_gif_remover(self) -> None:
"""
Regularly cleans old GIF timestamps
Parameters
----------
self : GifLimiter
The GifLimiter instance.
"""
current_time: int = int(time())
async with self.gif_lock:
for channel_id, timestamps in list(self.recent_gifs_by_channel.items()):
self.recent_gifs_by_channel[channel_id] = [
t for t in timestamps if current_time - t < self.recent_gif_age
]
for user_id, timestamps in list(self.recent_gifs_by_user.items()):
if filtered_timestamps := [t for t in timestamps if current_time - t < self.recent_gif_age]:
self.recent_gifs_by_user[user_id] = filtered_timestamps
else:
del self.recent_gifs_by_user[user_id]