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:
@@ -4,40 +4,59 @@ import logging
|
||||
from enum import Enum, auto
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any, List, Optional, Callable, TypeVar, Union, TypedDict, ClassVar, Tuple
|
||||
import discord
|
||||
from typing import (
|
||||
Dict,
|
||||
Any,
|
||||
List,
|
||||
Optional,
|
||||
Callable,
|
||||
TypeVar,
|
||||
Union,
|
||||
TypedDict,
|
||||
ClassVar,
|
||||
Tuple,
|
||||
)
|
||||
import discord # type: ignore
|
||||
|
||||
from .utils.exceptions import DisplayError
|
||||
from ..utils.exceptions import DisplayError
|
||||
|
||||
logger = logging.getLogger("VideoArchiver")
|
||||
|
||||
T = TypeVar('T')
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class DisplayTheme(TypedDict):
|
||||
"""Type definition for display theme"""
|
||||
|
||||
title_color: discord.Color
|
||||
success_color: discord.Color
|
||||
warning_color: discord.Color
|
||||
error_color: discord.Color
|
||||
info_color: discord.Color
|
||||
|
||||
|
||||
class DisplaySection(Enum):
|
||||
"""Available display sections"""
|
||||
|
||||
QUEUE_STATS = auto()
|
||||
DOWNLOADS = auto()
|
||||
COMPRESSIONS = auto()
|
||||
ERRORS = auto()
|
||||
HARDWARE = auto()
|
||||
|
||||
|
||||
class DisplayCondition(Enum):
|
||||
"""Display conditions for sections"""
|
||||
|
||||
HAS_ERRORS = "has_errors"
|
||||
HAS_DOWNLOADS = "has_downloads"
|
||||
HAS_COMPRESSIONS = "has_compressions"
|
||||
|
||||
|
||||
@dataclass
|
||||
class DisplayTemplate:
|
||||
"""Template for status display sections"""
|
||||
|
||||
name: str
|
||||
format_string: str
|
||||
inline: bool = False
|
||||
@@ -46,27 +65,28 @@ class DisplayTemplate:
|
||||
formatter: Optional[Callable[[Dict[str, Any]], str]] = None
|
||||
max_items: int = field(default=5) # Maximum items to display in lists
|
||||
|
||||
|
||||
class StatusFormatter:
|
||||
"""Formats status information for display"""
|
||||
|
||||
BYTE_UNITS: ClassVar[List[str]] = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||
BYTE_UNITS: ClassVar[List[str]] = ["B", "KB", "MB", "GB", "TB"]
|
||||
TIME_THRESHOLDS: ClassVar[List[Tuple[float, str]]] = [
|
||||
(60, 's'),
|
||||
(3600, 'm'),
|
||||
(float('inf'), 'h')
|
||||
(60, "s"),
|
||||
(3600, "m"),
|
||||
(float("inf"), "h"),
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def format_bytes(bytes_value: Union[int, float]) -> str:
|
||||
"""
|
||||
Format bytes into human readable format.
|
||||
|
||||
|
||||
Args:
|
||||
bytes_value: Number of bytes to format
|
||||
|
||||
|
||||
Returns:
|
||||
Formatted string with appropriate unit
|
||||
|
||||
|
||||
Raises:
|
||||
ValueError: If bytes_value is negative
|
||||
"""
|
||||
@@ -84,13 +104,13 @@ class StatusFormatter:
|
||||
def format_time(seconds: float) -> str:
|
||||
"""
|
||||
Format time duration.
|
||||
|
||||
|
||||
Args:
|
||||
seconds: Number of seconds to format
|
||||
|
||||
|
||||
Returns:
|
||||
Formatted time string
|
||||
|
||||
|
||||
Raises:
|
||||
ValueError: If seconds is negative
|
||||
"""
|
||||
@@ -107,13 +127,13 @@ class StatusFormatter:
|
||||
def format_percentage(value: float) -> str:
|
||||
"""
|
||||
Format percentage value.
|
||||
|
||||
|
||||
Args:
|
||||
value: Percentage value to format (0-100)
|
||||
|
||||
|
||||
Returns:
|
||||
Formatted percentage string
|
||||
|
||||
|
||||
Raises:
|
||||
ValueError: If value is outside valid range
|
||||
"""
|
||||
@@ -125,14 +145,14 @@ class StatusFormatter:
|
||||
def truncate_url(url: str, max_length: int = 50) -> str:
|
||||
"""
|
||||
Truncate URL to specified length.
|
||||
|
||||
|
||||
Args:
|
||||
url: URL to truncate
|
||||
max_length: Maximum length for URL
|
||||
|
||||
|
||||
Returns:
|
||||
Truncated URL string
|
||||
|
||||
|
||||
Raises:
|
||||
ValueError: If max_length is less than 4
|
||||
"""
|
||||
@@ -140,6 +160,7 @@ class StatusFormatter:
|
||||
raise ValueError("max_length must be at least 4")
|
||||
return f"{url[:max_length]}..." if len(url) > max_length else url
|
||||
|
||||
|
||||
class DisplayManager:
|
||||
"""Manages status display configuration"""
|
||||
|
||||
@@ -148,7 +169,7 @@ class DisplayManager:
|
||||
success_color=discord.Color.green(),
|
||||
warning_color=discord.Color.gold(),
|
||||
error_color=discord.Color.red(),
|
||||
info_color=discord.Color.blurple()
|
||||
info_color=discord.Color.blurple(),
|
||||
)
|
||||
|
||||
def __init__(self) -> None:
|
||||
@@ -165,7 +186,7 @@ class DisplayManager:
|
||||
"Avg Processing Time: {avg_processing_time}\n"
|
||||
"```"
|
||||
),
|
||||
order=1
|
||||
order=1,
|
||||
),
|
||||
DisplaySection.DOWNLOADS: DisplayTemplate(
|
||||
name="Active Downloads",
|
||||
@@ -181,7 +202,7 @@ class DisplayManager:
|
||||
"```"
|
||||
),
|
||||
order=2,
|
||||
condition=DisplayCondition.HAS_DOWNLOADS
|
||||
condition=DisplayCondition.HAS_DOWNLOADS,
|
||||
),
|
||||
DisplaySection.COMPRESSIONS: DisplayTemplate(
|
||||
name="Active Compressions",
|
||||
@@ -198,13 +219,13 @@ class DisplayManager:
|
||||
"```"
|
||||
),
|
||||
order=3,
|
||||
condition=DisplayCondition.HAS_COMPRESSIONS
|
||||
condition=DisplayCondition.HAS_COMPRESSIONS,
|
||||
),
|
||||
DisplaySection.ERRORS: DisplayTemplate(
|
||||
name="Error Statistics",
|
||||
format_string="```\n{error_stats}```",
|
||||
condition=DisplayCondition.HAS_ERRORS,
|
||||
order=4
|
||||
order=4,
|
||||
),
|
||||
DisplaySection.HARDWARE: DisplayTemplate(
|
||||
name="Hardware Statistics",
|
||||
@@ -215,11 +236,12 @@ class DisplayManager:
|
||||
"Peak Memory Usage: {memory_usage}\n"
|
||||
"```"
|
||||
),
|
||||
order=5
|
||||
)
|
||||
order=5,
|
||||
),
|
||||
}
|
||||
self.theme = self.DEFAULT_THEME.copy()
|
||||
|
||||
|
||||
class StatusDisplay:
|
||||
"""Handles formatting and display of queue status information"""
|
||||
|
||||
@@ -229,20 +251,18 @@ class StatusDisplay:
|
||||
|
||||
@classmethod
|
||||
async def create_queue_status_embed(
|
||||
cls,
|
||||
queue_status: Dict[str, Any],
|
||||
active_ops: Dict[str, Any]
|
||||
cls, queue_status: Dict[str, Any], active_ops: Dict[str, Any]
|
||||
) -> discord.Embed:
|
||||
"""
|
||||
Create an embed displaying queue status and active operations.
|
||||
|
||||
|
||||
Args:
|
||||
queue_status: Dictionary containing queue status information
|
||||
active_ops: Dictionary containing active operations information
|
||||
|
||||
|
||||
Returns:
|
||||
Discord embed containing formatted status information
|
||||
|
||||
|
||||
Raises:
|
||||
DisplayError: If there's an error creating the embed
|
||||
"""
|
||||
@@ -251,13 +271,12 @@ class StatusDisplay:
|
||||
embed = discord.Embed(
|
||||
title="Queue Status Details",
|
||||
color=display.display_manager.theme["title_color"],
|
||||
timestamp=datetime.utcnow()
|
||||
timestamp=datetime.utcnow(),
|
||||
)
|
||||
|
||||
# Add sections in order
|
||||
sections = sorted(
|
||||
display.display_manager.templates.items(),
|
||||
key=lambda x: x[1].order
|
||||
display.display_manager.templates.items(), key=lambda x: x[1].order
|
||||
)
|
||||
|
||||
for section, template in sections:
|
||||
@@ -265,9 +284,7 @@ class StatusDisplay:
|
||||
# Check condition if exists
|
||||
if template.condition:
|
||||
if not display._check_condition(
|
||||
template.condition,
|
||||
queue_status,
|
||||
active_ops
|
||||
template.condition, queue_status, active_ops
|
||||
):
|
||||
continue
|
||||
|
||||
@@ -275,9 +292,13 @@ class StatusDisplay:
|
||||
if section == DisplaySection.QUEUE_STATS:
|
||||
display._add_queue_statistics(embed, queue_status, template)
|
||||
elif section == DisplaySection.DOWNLOADS:
|
||||
display._add_active_downloads(embed, active_ops.get('downloads', {}), template)
|
||||
display._add_active_downloads(
|
||||
embed, active_ops.get("downloads", {}), template
|
||||
)
|
||||
elif section == DisplaySection.COMPRESSIONS:
|
||||
display._add_active_compressions(embed, active_ops.get('compressions', {}), template)
|
||||
display._add_active_compressions(
|
||||
embed, active_ops.get("compressions", {}), template
|
||||
)
|
||||
elif section == DisplaySection.ERRORS:
|
||||
display._add_error_statistics(embed, queue_status, template)
|
||||
elif section == DisplaySection.HARDWARE:
|
||||
@@ -297,7 +318,7 @@ class StatusDisplay:
|
||||
self,
|
||||
condition: DisplayCondition,
|
||||
queue_status: Dict[str, Any],
|
||||
active_ops: Dict[str, Any]
|
||||
active_ops: Dict[str, Any],
|
||||
) -> bool:
|
||||
"""Check if condition for displaying section is met"""
|
||||
try:
|
||||
@@ -316,185 +337,214 @@ class StatusDisplay:
|
||||
self,
|
||||
embed: discord.Embed,
|
||||
queue_status: Dict[str, Any],
|
||||
template: DisplayTemplate
|
||||
template: DisplayTemplate,
|
||||
) -> None:
|
||||
"""Add queue statistics to the embed"""
|
||||
try:
|
||||
metrics = queue_status.get('metrics', {})
|
||||
metrics = queue_status.get("metrics", {})
|
||||
embed.add_field(
|
||||
name=template.name,
|
||||
value=template.format_string.format(
|
||||
pending=queue_status.get('pending', 0),
|
||||
processing=queue_status.get('processing', 0),
|
||||
completed=queue_status.get('completed', 0),
|
||||
failed=queue_status.get('failed', 0),
|
||||
pending=queue_status.get("pending", 0),
|
||||
processing=queue_status.get("processing", 0),
|
||||
completed=queue_status.get("completed", 0),
|
||||
failed=queue_status.get("failed", 0),
|
||||
success_rate=self.formatter.format_percentage(
|
||||
metrics.get('success_rate', 0) * 100
|
||||
metrics.get("success_rate", 0) * 100
|
||||
),
|
||||
avg_processing_time=self.formatter.format_time(
|
||||
metrics.get('avg_processing_time', 0)
|
||||
)
|
||||
metrics.get("avg_processing_time", 0)
|
||||
),
|
||||
),
|
||||
inline=template.inline
|
||||
inline=template.inline,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error adding queue statistics: {e}")
|
||||
embed.add_field(
|
||||
name=template.name,
|
||||
value="```\nError displaying queue statistics```",
|
||||
inline=template.inline
|
||||
inline=template.inline,
|
||||
)
|
||||
|
||||
def _add_active_downloads(
|
||||
self,
|
||||
embed: discord.Embed,
|
||||
downloads: Dict[str, Any],
|
||||
template: DisplayTemplate
|
||||
self, embed: discord.Embed, downloads: Dict[str, Any], template: DisplayTemplate
|
||||
) -> None:
|
||||
"""Add active downloads information to the embed"""
|
||||
try:
|
||||
if downloads:
|
||||
content = []
|
||||
for url, progress in list(downloads.items())[:template.max_items]:
|
||||
for url, progress in list(downloads.items())[: template.max_items]:
|
||||
try:
|
||||
content.append(template.format_string.format(
|
||||
url=self.formatter.truncate_url(url),
|
||||
percent=self.formatter.format_percentage(progress.get('percent', 0)),
|
||||
speed=progress.get('speed', 'N/A'),
|
||||
eta=progress.get('eta', 'N/A'),
|
||||
size=f"{self.formatter.format_bytes(progress.get('downloaded_bytes', 0))}/"
|
||||
f"{self.formatter.format_bytes(progress.get('total_bytes', 0))}",
|
||||
start_time=progress.get('start_time', 'N/A'),
|
||||
retries=progress.get('retries', 0)
|
||||
))
|
||||
content.append(
|
||||
template.format_string.format(
|
||||
url=self.formatter.truncate_url(url),
|
||||
percent=self.formatter.format_percentage(
|
||||
progress.get("percent", 0)
|
||||
),
|
||||
speed=progress.get("speed", "N/A"),
|
||||
eta=progress.get("eta", "N/A"),
|
||||
size=f"{self.formatter.format_bytes(progress.get('downloaded_bytes', 0))}/"
|
||||
f"{self.formatter.format_bytes(progress.get('total_bytes', 0))}",
|
||||
start_time=progress.get("start_time", "N/A"),
|
||||
retries=progress.get("retries", 0),
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error formatting download {url}: {e}")
|
||||
continue
|
||||
|
||||
if len(downloads) > template.max_items:
|
||||
content.append(f"\n... and {len(downloads) - template.max_items} more")
|
||||
content.append(
|
||||
f"\n... and {len(downloads) - template.max_items} more"
|
||||
)
|
||||
|
||||
embed.add_field(
|
||||
name=template.name,
|
||||
value="".join(content) if content else "```\nNo active downloads```",
|
||||
inline=template.inline
|
||||
value=(
|
||||
"".join(content) if content else "```\nNo active downloads```"
|
||||
),
|
||||
inline=template.inline,
|
||||
)
|
||||
else:
|
||||
embed.add_field(
|
||||
name=template.name,
|
||||
value="```\nNo active downloads```",
|
||||
inline=template.inline
|
||||
inline=template.inline,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error adding active downloads: {e}")
|
||||
embed.add_field(
|
||||
name=template.name,
|
||||
value="```\nError displaying downloads```",
|
||||
inline=template.inline
|
||||
inline=template.inline,
|
||||
)
|
||||
|
||||
def _add_active_compressions(
|
||||
self,
|
||||
embed: discord.Embed,
|
||||
compressions: Dict[str, Any],
|
||||
template: DisplayTemplate
|
||||
template: DisplayTemplate,
|
||||
) -> None:
|
||||
"""Add active compressions information to the embed"""
|
||||
try:
|
||||
if compressions:
|
||||
content = []
|
||||
for file_id, progress in list(compressions.items())[:template.max_items]:
|
||||
for file_id, progress in list(compressions.items())[
|
||||
: template.max_items
|
||||
]:
|
||||
try:
|
||||
content.append(template.format_string.format(
|
||||
filename=progress.get('filename', 'Unknown'),
|
||||
percent=self.formatter.format_percentage(progress.get('percent', 0)),
|
||||
elapsed_time=progress.get('elapsed_time', 'N/A'),
|
||||
input_size=self.formatter.format_bytes(progress.get('input_size', 0)),
|
||||
current_size=self.formatter.format_bytes(progress.get('current_size', 0)),
|
||||
target_size=self.formatter.format_bytes(progress.get('target_size', 0)),
|
||||
codec=progress.get('codec', 'Unknown'),
|
||||
hardware_accel=progress.get('hardware_accel', False)
|
||||
))
|
||||
content.append(
|
||||
template.format_string.format(
|
||||
filename=progress.get("filename", "Unknown"),
|
||||
percent=self.formatter.format_percentage(
|
||||
progress.get("percent", 0)
|
||||
),
|
||||
elapsed_time=progress.get("elapsed_time", "N/A"),
|
||||
input_size=self.formatter.format_bytes(
|
||||
progress.get("input_size", 0)
|
||||
),
|
||||
current_size=self.formatter.format_bytes(
|
||||
progress.get("current_size", 0)
|
||||
),
|
||||
target_size=self.formatter.format_bytes(
|
||||
progress.get("target_size", 0)
|
||||
),
|
||||
codec=progress.get("codec", "Unknown"),
|
||||
hardware_accel=progress.get("hardware_accel", False),
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error formatting compression {file_id}: {e}")
|
||||
continue
|
||||
|
||||
if len(compressions) > template.max_items:
|
||||
content.append(f"\n... and {len(compressions) - template.max_items} more")
|
||||
content.append(
|
||||
f"\n... and {len(compressions) - template.max_items} more"
|
||||
)
|
||||
|
||||
embed.add_field(
|
||||
name=template.name,
|
||||
value="".join(content) if content else "```\nNo active compressions```",
|
||||
inline=template.inline
|
||||
value=(
|
||||
"".join(content)
|
||||
if content
|
||||
else "```\nNo active compressions```"
|
||||
),
|
||||
inline=template.inline,
|
||||
)
|
||||
else:
|
||||
embed.add_field(
|
||||
name=template.name,
|
||||
value="```\nNo active compressions```",
|
||||
inline=template.inline
|
||||
inline=template.inline,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error adding active compressions: {e}")
|
||||
embed.add_field(
|
||||
name=template.name,
|
||||
value="```\nError displaying compressions```",
|
||||
inline=template.inline
|
||||
inline=template.inline,
|
||||
)
|
||||
|
||||
def _add_error_statistics(
|
||||
self,
|
||||
embed: discord.Embed,
|
||||
queue_status: Dict[str, Any],
|
||||
template: DisplayTemplate
|
||||
template: DisplayTemplate,
|
||||
) -> None:
|
||||
"""Add error statistics to the embed"""
|
||||
try:
|
||||
metrics = queue_status.get('metrics', {})
|
||||
errors_by_type = metrics.get('errors_by_type', {})
|
||||
metrics = queue_status.get("metrics", {})
|
||||
errors_by_type = metrics.get("errors_by_type", {})
|
||||
if errors_by_type:
|
||||
error_stats = "\n".join(
|
||||
f"{error_type}: {count}"
|
||||
for error_type, count in list(errors_by_type.items())[:template.max_items]
|
||||
for error_type, count in list(errors_by_type.items())[
|
||||
: template.max_items
|
||||
]
|
||||
)
|
||||
if len(errors_by_type) > template.max_items:
|
||||
error_stats += f"\n... and {len(errors_by_type) - template.max_items} more"
|
||||
error_stats += (
|
||||
f"\n... and {len(errors_by_type) - template.max_items} more"
|
||||
)
|
||||
embed.add_field(
|
||||
name=template.name,
|
||||
value=template.format_string.format(error_stats=error_stats),
|
||||
inline=template.inline
|
||||
inline=template.inline,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error adding error statistics: {e}")
|
||||
embed.add_field(
|
||||
name=template.name,
|
||||
value="```\nError displaying error statistics```",
|
||||
inline=template.inline
|
||||
inline=template.inline,
|
||||
)
|
||||
|
||||
def _add_hardware_statistics(
|
||||
self,
|
||||
embed: discord.Embed,
|
||||
queue_status: Dict[str, Any],
|
||||
template: DisplayTemplate
|
||||
template: DisplayTemplate,
|
||||
) -> None:
|
||||
"""Add hardware statistics to the embed"""
|
||||
try:
|
||||
metrics = queue_status.get('metrics', {})
|
||||
metrics = queue_status.get("metrics", {})
|
||||
embed.add_field(
|
||||
name=template.name,
|
||||
value=template.format_string.format(
|
||||
hw_failures=metrics.get('hardware_accel_failures', 0),
|
||||
comp_failures=metrics.get('compression_failures', 0),
|
||||
hw_failures=metrics.get("hardware_accel_failures", 0),
|
||||
comp_failures=metrics.get("compression_failures", 0),
|
||||
memory_usage=self.formatter.format_bytes(
|
||||
metrics.get('peak_memory_usage', 0) * 1024 * 1024 # Convert MB to bytes
|
||||
)
|
||||
metrics.get("peak_memory_usage", 0)
|
||||
* 1024
|
||||
* 1024 # Convert MB to bytes
|
||||
),
|
||||
),
|
||||
inline=template.inline
|
||||
inline=template.inline,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error adding hardware statistics: {e}")
|
||||
embed.add_field(
|
||||
name=template.name,
|
||||
value="```\nError displaying hardware statistics```",
|
||||
inline=template.inline
|
||||
inline=template.inline,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user