feat: add Usage Limits Panel component with usage tracking and visual indicators for limits

style: implement custom color schemes and gradients for account section, enhancing visual hierarchy
This commit is contained in:
IGNY8 VPS (Salman)
2025-12-12 13:15:15 +00:00
parent 12956ec64a
commit 6e2101d019
29 changed files with 3622 additions and 85 deletions

View File

@@ -0,0 +1,137 @@
"""
Word Counter Utility
Standardized word counting from HTML content
Single source of truth for Content.word_count calculation
"""
import re
import logging
logger = logging.getLogger(__name__)
# Try to import BeautifulSoup, fallback to regex if not available
try:
from bs4 import BeautifulSoup
HAS_BEAUTIFULSOUP = True
except ImportError:
HAS_BEAUTIFULSOUP = False
logger.warning("BeautifulSoup4 not available, using regex fallback for word counting")
def calculate_word_count(html_content: str) -> int:
"""
Calculate word count from HTML content by stripping tags and counting words.
This is the SINGLE SOURCE OF TRUTH for word counting in IGNY8.
All limit tracking and billing should use Content.word_count which is calculated using this function.
Args:
html_content: HTML string to count words from
Returns:
int: Number of words in the content
Examples:
>>> calculate_word_count("<p>Hello world</p>")
2
>>> calculate_word_count("<h1>Title</h1><p>This is a paragraph.</p>")
5
>>> calculate_word_count("")
0
>>> calculate_word_count(None)
0
"""
# Handle None or empty content
if not html_content or not isinstance(html_content, str):
return 0
html_content = html_content.strip()
if not html_content:
return 0
try:
# Use BeautifulSoup if available (more accurate)
if HAS_BEAUTIFULSOUP:
soup = BeautifulSoup(html_content, 'html.parser')
# Get text, removing all HTML tags
text = soup.get_text(separator=' ', strip=True)
else:
# Fallback to regex (less accurate but functional)
# Remove all HTML tags
text = re.sub(r'<[^>]+>', ' ', html_content)
# Remove extra whitespace
text = ' '.join(text.split())
# Count words (split on whitespace)
if not text:
return 0
words = text.split()
word_count = len(words)
logger.debug(f"Calculated word count: {word_count} from {len(html_content)} chars of HTML")
return word_count
except Exception as e:
logger.error(f"Error calculating word count: {e}", exc_info=True)
# Return 0 on error rather than failing
return 0
def format_word_count(word_count: int) -> str:
"""
Format word count for display (e.g., 1000 -> "1K", 100000 -> "100K")
Args:
word_count: Number of words
Returns:
str: Formatted word count
Examples:
>>> format_word_count(500)
'500'
>>> format_word_count(1500)
'1.5K'
>>> format_word_count(100000)
'100K'
>>> format_word_count(1500000)
'1.5M'
"""
if word_count >= 1000000:
return f"{word_count / 1000000:.1f}M"
elif word_count >= 1000:
# Show .5K if not a whole number, otherwise just show K
result = word_count / 1000
if result == int(result):
return f"{int(result)}K"
return f"{result:.1f}K"
return str(word_count)
def validate_word_count_limit(current_words: int, requested_words: int, limit: int) -> dict:
"""
Validate if requested word generation would exceed limit.
Args:
current_words: Current word count used in period
requested_words: Words being requested
limit: Maximum words allowed
Returns:
dict with:
- allowed (bool): Whether operation is allowed
- remaining (int): Remaining words available
- would_exceed_by (int): How many words over limit if not allowed
"""
remaining = max(0, limit - current_words)
allowed = current_words + requested_words <= limit
would_exceed_by = max(0, (current_words + requested_words) - limit)
return {
'allowed': allowed,
'remaining': remaining,
'would_exceed_by': would_exceed_by,
'current': current_words,
'requested': requested_words,
'limit': limit,
}