feat: Implement bot response rate limiting in listeners

This commit is contained in:
Slipstream 2025-05-28 15:42:36 -06:00
parent e5fc915dc5
commit 06269e6eec
Signed by: slipstream
GPG Key ID: 13E498CE010AC6FD
2 changed files with 41 additions and 2 deletions

View File

@ -193,6 +193,10 @@ INTERNAL_ACTION_INTERVAL_SECONDS = int(os.getenv("INTERNAL_ACTION_INTERVAL_SECON
INTERNAL_ACTION_PROBABILITY = float(os.getenv("INTERNAL_ACTION_PROBABILITY", 0.5)) # Chance of performing an action each interval (10%)
AUTONOMOUS_ACTION_REPORT_CHANNEL_ID = os.getenv("GURT_AUTONOMOUS_ACTION_REPORT_CHANNEL_ID", 1366840485355982869) # Optional channel ID to report autonomous actions
# --- Bot Response Rate Limit Config ---
BOT_RESPONSE_RATE_LIMIT_PER_MINUTE = int(os.getenv("GURT_BOT_RESPONSE_RATE_LIMIT_PER_MINUTE", 5))
BOT_RESPONSE_RATE_LIMIT_WINDOW_SECONDS = 60 # 1 minute
# --- Topic Tracking Config ---
TOPIC_UPDATE_INTERVAL = 300 # Update topics every 5 minutes
TOPIC_RELEVANCE_DECAY = 0.2

View File

@ -6,10 +6,15 @@ import time
import re
import os # Added for file handling in error case
from typing import TYPE_CHECKING, List, Union, Dict, Any, Optional
from collections import deque # Import deque for efficient rate limiting
# Relative imports
from .utils import format_message # Import format_message
from .config import CONTEXT_WINDOW_SIZE # Import context window size
from .config import (
CONTEXT_WINDOW_SIZE, # Import context window size
BOT_RESPONSE_RATE_LIMIT_PER_MINUTE, # New config
BOT_RESPONSE_RATE_LIMIT_WINDOW_SECONDS # New config
)
# Assuming api, utils, analysis functions are defined and imported correctly later
# We might need to adjust these imports based on final structure
# from .api import get_ai_response, get_proactive_ai_response
@ -51,7 +56,7 @@ async def on_message_listener(cog: 'GurtCog', message: discord.Message):
from .api import get_ai_response, get_proactive_ai_response
from .utils import format_message, simulate_human_typing
from .analysis import analyze_message_sentiment, update_conversation_sentiment, identify_conversation_topics
from .config import GURT_RESPONSES, IGNORED_CHANNEL_IDS # Import simple responses and ignored channel IDs
from .config import GURT_RESPONSES, IGNORED_CHANNEL_IDS, BOT_RESPONSE_RATE_LIMIT_PER_MINUTE, BOT_RESPONSE_RATE_LIMIT_WINDOW_SECONDS # Import new config
# Don't respond to our own messages
if message.author == cog.bot.user:
@ -67,6 +72,26 @@ async def on_message_listener(cog: 'GurtCog', message: discord.Message):
if message.content.startswith(cog.bot.command_prefix):
return
# --- Bot Response Rate Limiting ---
if message.author.bot:
bot_id = message.author.id
if not hasattr(cog, 'bot_response_timestamps'):
cog.bot_response_timestamps = {}
if bot_id not in cog.bot_response_timestamps:
cog.bot_response_timestamps[bot_id] = deque()
# Clean up old timestamps
now = time.time()
while cog.bot_response_timestamps[bot_id] and \
now - cog.bot_response_timestamps[bot_id][0] > BOT_RESPONSE_RATE_LIMIT_WINDOW_SECONDS:
cog.bot_response_timestamps[bot_id].popleft()
# Check if limit is exceeded
if len(cog.bot_response_timestamps[bot_id]) >= BOT_RESPONSE_RATE_LIMIT_PER_MINUTE:
print(f"Rate limit exceeded for bot {message.author.name} ({bot_id}). Skipping response.")
return # Do not respond to this bot
# --- Cache and Track Incoming Message ---
try:
formatted_message = format_message(cog, message) # Use utility function
@ -497,6 +522,16 @@ async def on_message_listener(cog: 'GurtCog', message: discord.Message):
cog.gurt_participation_topics[topic] += 1
print(f"Tracked Gurt participation ({response_label}) in topic: '{topic}'")
print(f"Sent {response_label} content (Reply: {bool(message_reference)}, Stickers: {len(discord_stickers_to_send)}).")
# --- Record Gurt's response to a bot for rate limiting ---
if original_message.author.bot:
bot_id = original_message.author.id
# Ensure the deque exists (it should from the check at the start of on_message_listener)
if bot_id not in cog.bot_response_timestamps:
cog.bot_response_timestamps[bot_id] = deque()
cog.bot_response_timestamps[bot_id].append(time.time())
print(f"Recorded Gurt's response to bot {original_message.author.name} ({bot_id}). Current count: {len(cog.bot_response_timestamps[bot_id])}")
return True
except Exception as send_e:
print(f"Error sending {response_label} content: {send_e}")