mirror of
https://github.com/pacnpal/Pac-cogs.git
synced 2025-12-20 02:41:06 -05:00
loads of import fixes
This commit is contained in:
@@ -1,25 +1,29 @@
|
||||
"""Message processing and URL extraction for VideoProcessor"""
|
||||
|
||||
import logging
|
||||
import asyncio
|
||||
from enum import Enum, auto
|
||||
from typing import Optional, Dict, Any, List, Tuple, Set, TypedDict, ClassVar
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from enum import auto, Enum
|
||||
from typing import Any, ClassVar, Dict, List, Optional, Set, Tuple, TypedDict
|
||||
|
||||
from .processor.url_extractor import URLExtractor, URLMetadata
|
||||
from .processor.message_validator import MessageValidator, ValidationError
|
||||
from .processor.queue_processor import QueueProcessor, QueuePriority
|
||||
from .processor.constants import REACTIONS
|
||||
from .queue.manager import EnhancedVideoQueueManager
|
||||
from .config_manager import ConfigManager
|
||||
from .utils.exceptions import MessageHandlerError
|
||||
import discord # type: ignore
|
||||
from discord.ext import commands # type: ignore
|
||||
|
||||
from ..config_manager import ConfigManager
|
||||
from ..processor.constants import REACTIONS
|
||||
from ..processor.message_validator import MessageValidator, ValidationError
|
||||
from ..processor.queue_processor import QueuePriority, QueueProcessor
|
||||
|
||||
from ..processor.url_extractor import URLExtractor, URLMetadata
|
||||
from ..queue.manager import EnhancedVideoQueueManager
|
||||
from ..utils.exceptions import MessageHandlerError
|
||||
|
||||
logger = logging.getLogger("VideoArchiver")
|
||||
|
||||
|
||||
class MessageState(Enum):
|
||||
"""Possible states of message processing"""
|
||||
|
||||
RECEIVED = auto()
|
||||
VALIDATING = auto()
|
||||
EXTRACTING = auto()
|
||||
@@ -28,21 +32,27 @@ class MessageState(Enum):
|
||||
FAILED = auto()
|
||||
IGNORED = auto()
|
||||
|
||||
|
||||
class ProcessingStage(Enum):
|
||||
"""Message processing stages"""
|
||||
|
||||
VALIDATION = auto()
|
||||
EXTRACTION = auto()
|
||||
QUEUEING = auto()
|
||||
COMPLETION = auto()
|
||||
|
||||
|
||||
class MessageCacheEntry(TypedDict):
|
||||
"""Type definition for message cache entry"""
|
||||
|
||||
valid: bool
|
||||
reason: Optional[str]
|
||||
timestamp: str
|
||||
|
||||
|
||||
class MessageStatus(TypedDict):
|
||||
"""Type definition for message status"""
|
||||
|
||||
state: Optional[MessageState]
|
||||
stage: Optional[ProcessingStage]
|
||||
error: Optional[str]
|
||||
@@ -50,6 +60,7 @@ class MessageStatus(TypedDict):
|
||||
end_time: Optional[datetime]
|
||||
duration: Optional[float]
|
||||
|
||||
|
||||
class MessageCache:
|
||||
"""Caches message validation results"""
|
||||
|
||||
@@ -61,7 +72,7 @@ class MessageCache:
|
||||
def add(self, message_id: int, result: MessageCacheEntry) -> None:
|
||||
"""
|
||||
Add a result to cache.
|
||||
|
||||
|
||||
Args:
|
||||
message_id: Discord message ID
|
||||
result: Validation result entry
|
||||
@@ -74,10 +85,10 @@ class MessageCache:
|
||||
def get(self, message_id: int) -> Optional[MessageCacheEntry]:
|
||||
"""
|
||||
Get a cached result.
|
||||
|
||||
|
||||
Args:
|
||||
message_id: Discord message ID
|
||||
|
||||
|
||||
Returns:
|
||||
Cached validation entry or None if not found
|
||||
"""
|
||||
@@ -94,6 +105,7 @@ class MessageCache:
|
||||
del self._cache[oldest]
|
||||
del self._access_times[oldest]
|
||||
|
||||
|
||||
class ProcessingTracker:
|
||||
"""Tracks message processing state and progress"""
|
||||
|
||||
@@ -109,7 +121,7 @@ class ProcessingTracker:
|
||||
def start_processing(self, message_id: int) -> None:
|
||||
"""
|
||||
Start tracking a message.
|
||||
|
||||
|
||||
Args:
|
||||
message_id: Discord message ID
|
||||
"""
|
||||
@@ -121,11 +133,11 @@ class ProcessingTracker:
|
||||
message_id: int,
|
||||
state: MessageState,
|
||||
stage: Optional[ProcessingStage] = None,
|
||||
error: Optional[str] = None
|
||||
error: Optional[str] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Update message state.
|
||||
|
||||
|
||||
Args:
|
||||
message_id: Discord message ID
|
||||
state: New message state
|
||||
@@ -143,16 +155,16 @@ class ProcessingTracker:
|
||||
def get_status(self, message_id: int) -> MessageStatus:
|
||||
"""
|
||||
Get processing status for a message.
|
||||
|
||||
|
||||
Args:
|
||||
message_id: Discord message ID
|
||||
|
||||
|
||||
Returns:
|
||||
Dictionary containing message status information
|
||||
"""
|
||||
end_time = self.end_times.get(message_id)
|
||||
start_time = self.start_times.get(message_id)
|
||||
|
||||
|
||||
return MessageStatus(
|
||||
state=self.states.get(message_id),
|
||||
stage=self.stages.get(message_id),
|
||||
@@ -163,29 +175,32 @@ class ProcessingTracker:
|
||||
(end_time - start_time).total_seconds()
|
||||
if end_time and start_time
|
||||
else None
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
def is_message_stuck(self, message_id: int) -> bool:
|
||||
"""
|
||||
Check if a message is stuck in processing.
|
||||
|
||||
|
||||
Args:
|
||||
message_id: Discord message ID
|
||||
|
||||
|
||||
Returns:
|
||||
True if message is stuck, False otherwise
|
||||
"""
|
||||
if message_id not in self.states or message_id not in self.start_times:
|
||||
return False
|
||||
|
||||
|
||||
state = self.states[message_id]
|
||||
if state in (MessageState.COMPLETED, MessageState.FAILED, MessageState.IGNORED):
|
||||
return False
|
||||
|
||||
processing_time = (datetime.utcnow() - self.start_times[message_id]).total_seconds()
|
||||
|
||||
processing_time = (
|
||||
datetime.utcnow() - self.start_times[message_id]
|
||||
).total_seconds()
|
||||
return processing_time > self.MAX_PROCESSING_TIME
|
||||
|
||||
|
||||
class MessageHandler:
|
||||
"""Handles processing of messages for video content"""
|
||||
|
||||
@@ -193,14 +208,14 @@ class MessageHandler:
|
||||
self,
|
||||
bot: discord.Client,
|
||||
config_manager: ConfigManager,
|
||||
queue_manager: EnhancedVideoQueueManager
|
||||
queue_manager: EnhancedVideoQueueManager,
|
||||
) -> None:
|
||||
self.bot = bot
|
||||
self.config_manager = config_manager
|
||||
self.url_extractor = URLExtractor()
|
||||
self.message_validator = MessageValidator()
|
||||
self.queue_processor = QueueProcessor(queue_manager)
|
||||
|
||||
|
||||
# Initialize tracking and caching
|
||||
self.tracker = ProcessingTracker()
|
||||
self.validation_cache = MessageCache()
|
||||
@@ -209,10 +224,10 @@ class MessageHandler:
|
||||
async def process_message(self, message: discord.Message) -> None:
|
||||
"""
|
||||
Process a message for video content.
|
||||
|
||||
|
||||
Args:
|
||||
message: Discord message to process
|
||||
|
||||
|
||||
Raises:
|
||||
MessageHandlerError: If there's an error during processing
|
||||
"""
|
||||
@@ -224,11 +239,7 @@ class MessageHandler:
|
||||
await self._process_message_internal(message)
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing message: {str(e)}", exc_info=True)
|
||||
self.tracker.update_state(
|
||||
message.id,
|
||||
MessageState.FAILED,
|
||||
error=str(e)
|
||||
)
|
||||
self.tracker.update_state(message.id, MessageState.FAILED, error=str(e))
|
||||
try:
|
||||
await message.add_reaction(REACTIONS["error"])
|
||||
except Exception as react_error:
|
||||
@@ -237,10 +248,10 @@ class MessageHandler:
|
||||
async def _process_message_internal(self, message: discord.Message) -> None:
|
||||
"""
|
||||
Internal message processing logic.
|
||||
|
||||
|
||||
Args:
|
||||
message: Discord message to process
|
||||
|
||||
|
||||
Raises:
|
||||
MessageHandlerError: If there's an error during processing
|
||||
"""
|
||||
@@ -260,43 +271,38 @@ class MessageHandler:
|
||||
else:
|
||||
# Validate message
|
||||
self.tracker.update_state(
|
||||
message.id,
|
||||
MessageState.VALIDATING,
|
||||
ProcessingStage.VALIDATION
|
||||
message.id, MessageState.VALIDATING, ProcessingStage.VALIDATION
|
||||
)
|
||||
try:
|
||||
is_valid, reason = await self.message_validator.validate_message(
|
||||
message,
|
||||
settings
|
||||
message, settings
|
||||
)
|
||||
# Cache result
|
||||
self.validation_cache.add(message.id, MessageCacheEntry(
|
||||
valid=is_valid,
|
||||
reason=reason,
|
||||
timestamp=datetime.utcnow().isoformat()
|
||||
))
|
||||
self.validation_cache.add(
|
||||
message.id,
|
||||
MessageCacheEntry(
|
||||
valid=is_valid,
|
||||
reason=reason,
|
||||
timestamp=datetime.utcnow().isoformat(),
|
||||
),
|
||||
)
|
||||
except ValidationError as e:
|
||||
raise MessageHandlerError(f"Validation failed: {str(e)}")
|
||||
|
||||
if not is_valid:
|
||||
logger.debug(f"Message validation failed: {reason}")
|
||||
self.tracker.update_state(
|
||||
message.id,
|
||||
MessageState.IGNORED,
|
||||
error=reason
|
||||
message.id, MessageState.IGNORED, error=reason
|
||||
)
|
||||
return
|
||||
|
||||
# Extract URLs
|
||||
self.tracker.update_state(
|
||||
message.id,
|
||||
MessageState.EXTRACTING,
|
||||
ProcessingStage.EXTRACTION
|
||||
message.id, MessageState.EXTRACTING, ProcessingStage.EXTRACTION
|
||||
)
|
||||
try:
|
||||
urls: List[URLMetadata] = await self.url_extractor.extract_urls(
|
||||
message,
|
||||
enabled_sites=settings.get("enabled_sites")
|
||||
message, enabled_sites=settings.get("enabled_sites")
|
||||
)
|
||||
if not urls:
|
||||
logger.debug("No valid URLs found in message")
|
||||
@@ -307,24 +313,18 @@ class MessageHandler:
|
||||
|
||||
# Process URLs
|
||||
self.tracker.update_state(
|
||||
message.id,
|
||||
MessageState.PROCESSING,
|
||||
ProcessingStage.QUEUEING
|
||||
message.id, MessageState.PROCESSING, ProcessingStage.QUEUEING
|
||||
)
|
||||
try:
|
||||
await self.queue_processor.process_urls(
|
||||
message,
|
||||
urls,
|
||||
priority=QueuePriority.NORMAL
|
||||
message, urls, priority=QueuePriority.NORMAL
|
||||
)
|
||||
except Exception as e:
|
||||
raise MessageHandlerError(f"Queue processing failed: {str(e)}")
|
||||
|
||||
# Mark completion
|
||||
self.tracker.update_state(
|
||||
message.id,
|
||||
MessageState.COMPLETED,
|
||||
ProcessingStage.COMPLETION
|
||||
message.id, MessageState.COMPLETED, ProcessingStage.COMPLETION
|
||||
)
|
||||
|
||||
except MessageHandlerError:
|
||||
@@ -333,35 +333,28 @@ class MessageHandler:
|
||||
raise MessageHandlerError(f"Unexpected error: {str(e)}")
|
||||
|
||||
async def format_archive_message(
|
||||
self,
|
||||
author: Optional[discord.Member],
|
||||
channel: discord.TextChannel,
|
||||
url: str
|
||||
self, author: Optional[discord.Member], channel: discord.TextChannel, url: str
|
||||
) -> str:
|
||||
"""
|
||||
Format message for archive channel.
|
||||
|
||||
|
||||
Args:
|
||||
author: Optional message author
|
||||
channel: Channel the message was posted in
|
||||
url: URL being archived
|
||||
|
||||
|
||||
Returns:
|
||||
Formatted message string
|
||||
"""
|
||||
return await self.queue_processor.format_archive_message(
|
||||
author,
|
||||
channel,
|
||||
url
|
||||
)
|
||||
return await self.queue_processor.format_archive_message(author, channel, url)
|
||||
|
||||
def get_message_status(self, message_id: int) -> MessageStatus:
|
||||
"""
|
||||
Get processing status for a message.
|
||||
|
||||
|
||||
Args:
|
||||
message_id: Discord message ID
|
||||
|
||||
|
||||
Returns:
|
||||
Dictionary containing message status information
|
||||
"""
|
||||
@@ -370,7 +363,7 @@ class MessageHandler:
|
||||
def is_healthy(self) -> bool:
|
||||
"""
|
||||
Check if handler is healthy.
|
||||
|
||||
|
||||
Returns:
|
||||
True if handler is healthy, False otherwise
|
||||
"""
|
||||
@@ -378,7 +371,9 @@ class MessageHandler:
|
||||
# Check for any stuck messages
|
||||
for message_id in self.tracker.states:
|
||||
if self.tracker.is_message_stuck(message_id):
|
||||
logger.warning(f"Message {message_id} appears to be stuck in processing")
|
||||
logger.warning(
|
||||
f"Message {message_id} appears to be stuck in processing"
|
||||
)
|
||||
return False
|
||||
return True
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user