mirror of
https://github.com/pacnpal/Pac-cogs.git
synced 2025-12-20 02:41:06 -05:00
Fixed the "cannot import name '_download_progress'" error by:
Adding a shared progress_tracker instance in processor/init.py Exposing public functions that wrap the ProgressTracker methods Removing direct access to private _download_progress variable Fixed the "'QueueItem' object has no attribute 'retry_count'" error by: Updating the QueueItem class in queue/models.py to use retry_count instead of retries This matches the field name used in the queue manager's implementation
This commit is contained in:
@@ -6,6 +6,7 @@ from .progress_tracker import ProgressTracker
|
||||
from .message_handler import MessageHandler
|
||||
from .queue_handler import QueueHandler
|
||||
|
||||
# Export public classes and constants
|
||||
__all__ = [
|
||||
'VideoProcessor',
|
||||
'REACTIONS',
|
||||
@@ -13,3 +14,27 @@ __all__ = [
|
||||
'MessageHandler',
|
||||
'QueueHandler'
|
||||
]
|
||||
|
||||
# Create a shared progress tracker instance for module-level access
|
||||
progress_tracker = ProgressTracker()
|
||||
|
||||
# Export progress tracking functions that wrap the instance methods
|
||||
def update_download_progress(url, progress_data):
|
||||
"""Update download progress for a specific URL"""
|
||||
progress_tracker.update_download_progress(url, progress_data)
|
||||
|
||||
def complete_download(url):
|
||||
"""Mark a download as complete"""
|
||||
progress_tracker.complete_download(url)
|
||||
|
||||
def increment_download_retries(url):
|
||||
"""Increment retry count for a download"""
|
||||
progress_tracker.increment_download_retries(url)
|
||||
|
||||
def get_download_progress(url=None):
|
||||
"""Get download progress for a specific URL or all downloads"""
|
||||
return progress_tracker.get_download_progress(url)
|
||||
|
||||
def get_active_operations():
|
||||
"""Get all active operations"""
|
||||
return progress_tracker.get_active_operations()
|
||||
|
||||
@@ -15,10 +15,11 @@ logger = logging.getLogger("VideoArchiver")
|
||||
class QueueHandler:
|
||||
"""Handles queue processing and video operations"""
|
||||
|
||||
def __init__(self, bot, config_manager, components):
|
||||
def __init__(self, bot, config_manager, components, db=None):
|
||||
self.bot = bot
|
||||
self.config = config_manager
|
||||
self.components = components
|
||||
self.db = db
|
||||
self._unloading = False
|
||||
self._active_downloads: Dict[str, asyncio.Task] = {}
|
||||
self._active_downloads_lock = asyncio.Lock()
|
||||
@@ -34,6 +35,16 @@ class QueueHandler:
|
||||
download_task = None
|
||||
|
||||
try:
|
||||
# Check if video is already archived
|
||||
if self.db and self.db.is_url_archived(item.url):
|
||||
logger.info(f"Video already archived: {item.url}")
|
||||
if original_message := await self._get_original_message(item):
|
||||
await original_message.add_reaction(REACTIONS["success"])
|
||||
archived_info = self.db.get_archived_video(item.url)
|
||||
if archived_info:
|
||||
await original_message.reply(f"This video was already archived. You can find it here: {archived_info[0]}")
|
||||
return True, None
|
||||
|
||||
guild_id = item.guild_id
|
||||
if guild_id not in self.components:
|
||||
return False, f"No components found for guild {guild_id}"
|
||||
@@ -85,6 +96,65 @@ class QueueHandler:
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to clean up file {file_path}: {e}")
|
||||
|
||||
async def _archive_video(self, guild_id: int, original_message: Optional[discord.Message],
|
||||
message_manager, url: str, file_path: str) -> Tuple[bool, Optional[str]]:
|
||||
"""Archive downloaded video"""
|
||||
try:
|
||||
# Get archive channel
|
||||
guild = self.bot.get_guild(guild_id)
|
||||
if not guild:
|
||||
return False, f"Guild {guild_id} not found"
|
||||
|
||||
archive_channel = await self.config.get_channel(guild, "archive")
|
||||
if not archive_channel:
|
||||
return False, "Archive channel not configured"
|
||||
|
||||
# Format message
|
||||
try:
|
||||
author = original_message.author if original_message else None
|
||||
channel = original_message.channel if original_message else None
|
||||
message = await message_manager.format_message(
|
||||
author=author, channel=channel, url=url
|
||||
)
|
||||
except Exception as e:
|
||||
return False, f"Failed to format message: {str(e)}"
|
||||
|
||||
# Upload to archive channel
|
||||
if not os.path.exists(file_path):
|
||||
return False, "Processed file not found"
|
||||
|
||||
archive_message = await archive_channel.send(content=message, file=discord.File(file_path))
|
||||
|
||||
# Store in database if available
|
||||
if self.db and archive_message.attachments:
|
||||
discord_url = archive_message.attachments[0].url
|
||||
self.db.add_archived_video(
|
||||
url,
|
||||
discord_url,
|
||||
archive_message.id,
|
||||
archive_channel.id,
|
||||
guild_id
|
||||
)
|
||||
logger.info(f"Added video to archive database: {url} -> {discord_url}")
|
||||
|
||||
if original_message:
|
||||
await original_message.remove_reaction(REACTIONS["processing"], self.bot.user)
|
||||
await original_message.add_reaction(REACTIONS["success"])
|
||||
logger.info(f"Successfully processed message {original_message.id}")
|
||||
|
||||
return True, None
|
||||
|
||||
except discord.HTTPException as e:
|
||||
if original_message:
|
||||
await original_message.add_reaction(REACTIONS["error"])
|
||||
logger.error(f"Failed to upload to Discord: {str(e)}")
|
||||
return False, f"Failed to upload to Discord: {str(e)}"
|
||||
except Exception as e:
|
||||
if original_message:
|
||||
await original_message.add_reaction(REACTIONS["error"])
|
||||
logger.error(f"Failed to archive video: {str(e)}")
|
||||
return False, f"Failed to archive video: {str(e)}"
|
||||
|
||||
async def _get_original_message(self, item) -> Optional[discord.Message]:
|
||||
"""Retrieve the original message"""
|
||||
try:
|
||||
@@ -149,53 +219,6 @@ class QueueHandler:
|
||||
async with self._active_downloads_lock:
|
||||
self._active_downloads.pop(url, None)
|
||||
|
||||
async def _archive_video(self, guild_id: int, original_message: Optional[discord.Message],
|
||||
message_manager, url: str, file_path: str) -> Tuple[bool, Optional[str]]:
|
||||
"""Archive downloaded video"""
|
||||
try:
|
||||
# Get archive channel
|
||||
guild = self.bot.get_guild(guild_id)
|
||||
if not guild:
|
||||
return False, f"Guild {guild_id} not found"
|
||||
|
||||
archive_channel = await self.config.get_channel(guild, "archive")
|
||||
if not archive_channel:
|
||||
return False, "Archive channel not configured"
|
||||
|
||||
# Format message
|
||||
try:
|
||||
author = original_message.author if original_message else None
|
||||
channel = original_message.channel if original_message else None
|
||||
message = await message_manager.format_message(
|
||||
author=author, channel=channel, url=url
|
||||
)
|
||||
except Exception as e:
|
||||
return False, f"Failed to format message: {str(e)}"
|
||||
|
||||
# Upload to archive channel
|
||||
if not os.path.exists(file_path):
|
||||
return False, "Processed file not found"
|
||||
|
||||
await archive_channel.send(content=message, file=discord.File(file_path))
|
||||
|
||||
if original_message:
|
||||
await original_message.remove_reaction(REACTIONS["processing"], self.bot.user)
|
||||
await original_message.add_reaction(REACTIONS["success"])
|
||||
logger.info(f"Successfully processed message {original_message.id}")
|
||||
|
||||
return True, None
|
||||
|
||||
except discord.HTTPException as e:
|
||||
if original_message:
|
||||
await original_message.add_reaction(REACTIONS["error"])
|
||||
logger.error(f"Failed to upload to Discord: {str(e)}")
|
||||
return False, f"Failed to upload to Discord: {str(e)}"
|
||||
except Exception as e:
|
||||
if original_message:
|
||||
await original_message.add_reaction(REACTIONS["error"])
|
||||
logger.error(f"Failed to archive video: {str(e)}")
|
||||
return False, f"Failed to archive video: {str(e)}"
|
||||
|
||||
async def cleanup(self):
|
||||
"""Clean up resources and stop processing"""
|
||||
try:
|
||||
|
||||
@@ -12,11 +12,37 @@ REACTIONS = {
|
||||
'processing': '⚙️',
|
||||
'success': '✅',
|
||||
'error': '❌',
|
||||
'archived': '🔄', # New reaction for already archived videos
|
||||
'numbers': ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣'],
|
||||
'progress': ['⬛', '🟨', '🟩'],
|
||||
'download': ['0️⃣', '2️⃣', '4️⃣', '6️⃣', '8️⃣', '🔟']
|
||||
}
|
||||
|
||||
async def handle_archived_reaction(message: discord.Message, user: discord.User, db) -> None:
|
||||
"""Handle reaction to archived video message"""
|
||||
try:
|
||||
# Check if the reaction is from a user (not the bot) and is the archived reaction
|
||||
if user.bot or str(message.reactions[0].emoji) != REACTIONS['archived']:
|
||||
return
|
||||
|
||||
# Extract URLs from the message
|
||||
urls = []
|
||||
if message.content:
|
||||
for word in message.content.split():
|
||||
if any(s in word.lower() for s in ['http://', 'https://']):
|
||||
urls.append(word)
|
||||
|
||||
# Check each URL in the database
|
||||
for url in urls:
|
||||
result = db.get_archived_video(url)
|
||||
if result:
|
||||
discord_url = result[0]
|
||||
await message.reply(f"This video was already archived. You can find it here: {discord_url}")
|
||||
return
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error handling archived reaction: {e}")
|
||||
|
||||
async def update_queue_position_reaction(message: discord.Message, position: int, bot_user) -> None:
|
||||
"""Update queue position reaction"""
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user