Fixed Discord Integration:

Added missing discord import
Added proper error handling for all discord operations
Improved error reporting for discord-specific failures
Enhanced Error Handling:
Added try/except blocks around all major operations
Implemented proper cleanup in finally blocks
Added more specific error messages for debugging
Queue Processing Improvements:
Ensured the queue continues processing even if individual items fail
Added better file cleanup to prevent resource leaks
Improved error reporting to help diagnose issues
Resource Management:
Added proper cleanup of downloaded files
Improved handling of missing discord resources
Better management of failed downloads
This commit is contained in:
pacnpal
2024-11-15 13:36:26 +00:00
parent 887547473c
commit b4479c951b
4 changed files with 385 additions and 289 deletions

View File

@@ -3,8 +3,9 @@
import os
import logging
import asyncio
import discord # Added missing import
from pathlib import Path
from typing import Dict, Any, Optional
from typing import Dict, Any, Optional, Tuple
import traceback
from videoarchiver.enhanced_queue import EnhancedVideoQueueManager
@@ -27,12 +28,12 @@ class VideoProcessor:
config_manager,
components,
queue_manager=None,
ffmpeg_mgr=None # Add FFmpeg manager parameter
ffmpeg_mgr=None
):
self.bot = bot
self.config = config_manager
self.components = components
self.ffmpeg_mgr = ffmpeg_mgr # Store shared FFmpeg manager
self.ffmpeg_mgr = ffmpeg_mgr
# Use provided queue manager or create new one
if queue_manager:
@@ -92,72 +93,113 @@ class VideoProcessor:
logger.error(f"Error processing message: {traceback.format_exc()}")
raise ProcessingError(f"Failed to process message: {str(e)}")
async def _process_video(self, item):
async def _process_video(self, item) -> Tuple[bool, Optional[str]]:
"""Process a video from the queue"""
file_path = None
try:
guild_id = item.guild_id
if guild_id not in self.components:
raise ProcessingError(f"No components found for guild {guild_id}")
return False, f"No components found for guild {guild_id}"
components = self.components[guild_id]
downloader = components.get("downloader")
message_manager = components.get("message_manager")
if not downloader or not message_manager:
raise ProcessingError(f"Missing required components for guild {guild_id}")
return False, f"Missing required components for guild {guild_id}"
# Download and process video
success, file_path, error = await downloader.download_video(item.url)
if not success:
raise ProcessingError(f"Failed to download video: {error}")
# Get archive channel
guild = self.bot.get_guild(guild_id)
if not guild:
raise ProcessingError(f"Guild {guild_id} not found")
archive_channel = await self.config.get_channel(guild, "archive")
if not archive_channel:
raise ProcessingError("Archive channel not configured")
# Upload to archive channel
try:
original_message = await self.bot.get_channel(item.channel_id).fetch_message(item.message_id)
author = original_message.author if original_message else None
success, file_path, error = await downloader.download_video(item.url)
if not success:
return False, f"Failed to download video: {error}"
except Exception as e:
return False, f"Download error: {str(e)}"
message = await message_manager.format_message(
author=author,
channel=self.bot.get_channel(item.channel_id),
original_message=original_message
)
try:
# Get archive channel
guild = self.bot.get_guild(guild_id)
if not guild:
return False, f"Guild {guild_id} not found"
await archive_channel.send(content=message, file=discord.File(file_path))
archive_channel = await self.config.get_channel(guild, "archive")
if not archive_channel:
return False, "Archive channel not configured"
# Get original message
try:
channel = self.bot.get_channel(item.channel_id)
if not channel:
return False, f"Channel {item.channel_id} not found"
original_message = await channel.fetch_message(item.message_id)
except discord.NotFound:
original_message = None
except Exception as e:
logger.error(f"Error fetching original message: {e}")
original_message = None
# Format message
try:
author = original_message.author if original_message else None
message = await message_manager.format_message(
author=author,
channel=channel,
original_message=original_message
)
except Exception as e:
logger.error(f"Error formatting message: {e}")
message = f"Video from {item.url}"
# Upload to archive channel
try:
if not os.path.exists(file_path):
return False, "Processed file not found"
await archive_channel.send(
content=message,
file=discord.File(file_path)
)
except discord.HTTPException as e:
return False, f"Failed to upload to Discord: {str(e)}"
except Exception as e:
return False, f"Failed to archive video: {str(e)}"
# Delete original if configured
settings = await self.config.get_guild_settings(guild_id)
if settings.get("delete_after_repost", False) and original_message:
if original_message:
try:
await original_message.delete()
settings = await self.config.get_guild_settings(guild_id)
if settings.get("delete_after_repost", False):
await original_message.delete()
except Exception as e:
logger.warning(f"Failed to delete original message: {e}")
# Don't fail the process for deletion errors
return True, None
except Exception as e:
return False, f"Failed to archive video: {str(e)}"
return False, f"Processing error: {str(e)}"
finally:
# Clean up downloaded file
try:
if file_path and os.path.exists(file_path):
if file_path and os.path.exists(file_path):
try:
os.unlink(file_path)
except Exception as e:
logger.error(f"Failed to clean up file {file_path}: {e}")
except Exception as e:
logger.error(f"Failed to clean up file {file_path}: {e}")
# Don't fail the process for cleanup errors
except Exception as e:
logger.error(f"Error processing video: {traceback.format_exc()}")
return False, str(e)
finally:
# Ensure file cleanup even on unexpected errors
if file_path and os.path.exists(file_path):
try:
os.unlink(file_path)
except Exception as e:
logger.error(f"Final cleanup failed for {file_path}: {e}")
async def cleanup(self):
"""Clean up resources"""
try: