diff --git a/plugins/url_title_sniffer.py b/plugins/url_title_sniffer.py index a1d9f14..6eadcfe 100644 --- a/plugins/url_title_sniffer.py +++ b/plugins/url_title_sniffer.py @@ -12,7 +12,7 @@ Features: - Built-in exclusion of YouTube URLs to avoid conflicts with dedicated YouTube plugins - Error handling for network and parsing operations - Proper resource cleanup through session management - - Queue-based processing system for better flow control + - Queue-based processing system with strict rate limiting Dependencies: - aiohttp: For asynchronous HTTP requests @@ -25,6 +25,7 @@ Date: 2025-02-14 """ import re +import time import aiohttp import ircstyle from lxml import html @@ -46,6 +47,7 @@ class URLTitlePlugin: session (aiohttp.ClientSession): Persistent HTTP session for making web requests url_pattern (re.Pattern): Compiled regex for URL detection in messages queue (Queue): Processing queue for URL handling tasks + last_processed (float): Timestamp of last successful URL processing """ def __init__(self, bot): @@ -54,6 +56,7 @@ class URLTitlePlugin: self.session = aiohttp.ClientSession(loop=self.bot.loop) self.url_pattern = re.compile(r"https?://[^\s<>\"']+|www\.[^\s<>\"']+") self.queue = Queue() + self.last_processed = 0 # Initialize to epoch start self.bot.create_task(self.process_queue()) @event(irc3.rfc.PRIVMSG) @@ -68,14 +71,24 @@ class URLTitlePlugin: self.queue.put_nowait((target, url)) async def process_queue(self): - """Process URLs from the queue asynchronously.""" + """Process URLs from the queue with strict 5-second cooldown between requests.""" while True: target, url = await self.queue.get() try: + current_time = time.time() + elapsed = current_time - self.last_processed + + if elapsed < 5: + self.bot.log.info(f"Rate limited: Waiting {5 - elapsed:.1f}s to process {url}") + continue + title = await self.fetch_title(url) if title: formatted_message = self.format_message(title, url) await self.bot.privmsg(target, formatted_message) + + self.last_processed = time.time() # Update after successful processing + except Exception as e: self.bot.log.error(f"Error processing URL {url}: {e}") finally: @@ -113,4 +126,4 @@ class URLTitlePlugin: def __del__(self): """Ensure proper cleanup when the plugin is destroyed.""" - self.bot.create_task(self.close()) \ No newline at end of file + self.bot.create_task(self.close())