noumanjavaid's picture
Update app.py
3e8fb84 verified
raw
history blame
9.43 kB
import gradio as gr
import logging
import traceback
import time
import re
import os
from functools import wraps, lru_cache
from dotenv import load_dotenv
from urllib.parse import urlparse
# Load environment variables
load_dotenv()
# Enhanced logging configuration
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('centurion_platform.log', encoding='utf-8', mode='a'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
# CSS Configuration
css = """
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #ffffff;
color: #000000;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
.header {
background: #ffffff;
border-bottom: 1px solid #e5e5e5;
padding: 1rem 2rem;
display: flex;
align-items: center;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.logo {
width: 45px;
height: 45px;
margin-right: 15px;
transition: transform 0.3s ease;
}
.header-title {
color: #000000;
font-size: 24px;
font-weight: 600;
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 2rem;
background: #ffffff;
}
.main-content {
background: #ffffff;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
margin: 2rem 0;
overflow: hidden;
border: 1px solid #e5e5e5;
}
.iframe-container {
position: relative;
width: 100%;
height: 0;
padding-bottom: 65%;
background: #ffffff;
}
.iframe-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: none;
}
.nav-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
margin-top: 2rem;
}
.nav-card {
background: #ffffff;
border: 1px solid #e5e5e5;
border-radius: 10px;
padding: 1.5rem;
transition: all 0.3s ease;
}
@media (max-width: 768px) {
.nav-grid {
grid-template-columns: 1fr;
}
}
"""
# Performance and security decorators
def performance_monitor(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
try:
result = func(*args, **kwargs)
execution_time = time.time() - start
logger.info(f"{func.__name__} execution time: {execution_time:.2f} seconds")
return result
except Exception as e:
logger.error(f"Error in {func.__name__}: {e}")
logger.error(traceback.format_exc())
raise
return wrapper
# URL Validation and Sanitization
@lru_cache(maxsize=100)
def validate_and_sanitize_url(url):
"""
Comprehensive URL validation and sanitization
"""
try:
# Validate URL pattern
url_pattern = re.compile(
r'^https?://' # http:// or https://
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|' # domain...
r'localhost|' # localhost...
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
r'(?::\d+)?' # optional port
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
if not url_pattern.match(url):
logger.warning(f"Invalid URL format: {url}")
return None
# Parse and validate URL
parsed_url = urlparse(url)
# Whitelist allowed domains
allowed_domains = [
'noumanjavaid-new-space.hf.space',
'noumanjavaid-centurionv2.hf.space',
'noumanjavaid-watermark-demo-video.hf.space',
'noumanjavaid-centii.hf.space',
'localhost'
]
if parsed_url.netloc not in allowed_domains:
logger.warning(f"Unauthorized domain: {parsed_url.netloc}")
return None
return url
except Exception as e:
logger.error(f"URL validation error: {e}")
return None
# Platform Configuration
PLATFORM_CONFIG = {
'main_platform_url': os.getenv('MAIN_PLATFORM_URL', 'https://noumanjavaid-centii.hf.space'),
'launch_config': {
'show_error': True,
'show_api': False,
'show_tips': False,
'height': 800,
'analytics_enabled': False,
'enable_queue': False,
'prevent_thread_lock': True
}
}
# Error Notification (Optional)
def send_error_notification(error):
"""
Send error notifications via external service
"""
try:
import requests
webhook_url = os.getenv('ERROR_WEBHOOK_URL')
if webhook_url:
payload = {
"text": f"🚨 Centurion Platform Error: {str(error)}",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"```{traceback.format_exc()}```"
}
}
]
}
requests.post(webhook_url, json=payload)
except Exception as log_error:
logger.error(f"Error sending notification: {log_error}")
# Configuration Validation
def validate_configuration(demo):
"""
Validate Gradio demo configuration
"""
required_attributes = [
'title',
'css',
'show_error',
'show_api',
'show_tips',
'height',
'analytics_enabled',
'enable_queue'
]
validation_results = {}
for attr in required_attributes:
try:
value = getattr(demo, attr, None)
validation_results[attr] = value is not None
except Exception as e:
logger.error(f"Error validating {attr}: {e}")
validation_results[attr] = False
return validation_results
@performance_monitor
def create_demo():
"""
Create Gradio demo with comprehensive validation
"""
# Navigation Cards with URL Validation
cards = [
{
"icon": "πŸ”",
"title": "DeepFake Detection",
"url": validate_and_sanitize_url(os.getenv('DEEPFAKE_URL', 'https://noumanjavaid-new-space.hf.space'))
},
{
"icon": "πŸ“„",
"title": "Document Analysis", "url": validate_and_sanitize_url(os.getenv('DOCUMENT_URL', 'https://noumanjavaid-centurionv2.hf.space'))
},
{
"icon": "πŸŽ₯",
"title": "Video Watermarking",
"url": validate_and_sanitize_url(os.getenv('WATERMARK_URL', 'https://noumanjavaid-watermark-demo-video.hf.space'))
},
{
"icon": "πŸ”",
"title": "Image Authentication",
"url": validate_and_sanitize_url(os.getenv('AUTH_URL', 'https://noumanjavaid-centii.hf.space'))
},
]
# Validate navigation cards
invalid_cards = [card for card in cards if card['url'] is None]
if invalid_cards:
logger.warning(f"Invalid navigation card URLs: {invalid_cards}")
# Generate HTML for navigation cards
html_cards = "".join(
f'''
<div class="nav-card" role="navigation" aria-label="{card['title']}" tabindex="0">
<a href="{card['url']}" target="_blank" rel="noopener noreferrer">
{card['icon']} {card['title']}
</a>
</div>
''' for card in cards if card['url'] is not None
)
# Create Gradio block
with gr.Blocks(css=css, title="Centurion Analysis Platform") as demo:
# Header
with gr.Row(elem_classes=["header"]):
gr.Image(
"https://raw.githubusercontent.com/noumanjavaid96/ai-as-an-api/refs/heads/master/image%20(39).png",
elem_classes=["logo"],
show_label=False,
container=False
)
gr.Markdown("Centurion Analysis", elem_classes=["header-title"])
# Main content
with gr.Row(elem_classes=["container"]):
with gr.Column(elem_classes=["main-content"]):
gr.HTML(f'''
<div class="iframe-container">
<iframe
src="{PLATFORM_CONFIG['main_platform_url']}"
loading="lazy"
title="Centurion Main Platform"
></iframe>
</div>
''')
# Navigation grid
with gr.Row(elem_classes=["nav-grid"]):
gr.HTML(html_cards)
return demo
def main():
try:
demo = create_demo()
# Validate configuration before launching
config_validation = validate_configuration(demo)
logger.info(f"Configuration Validation: {config_validation}")
validation_errors = [k for k, v in config_validation.items() if not v]
if validation_errors:
logger.error(f"Configuration validation failed for: {validation_errors}")
raise ValueError(f"Invalid configuration: {validation_errors}")
demo.launch(**PLATFORM_CONFIG['launch_config'])
except Exception as e:
logger.critical(f"Application launch failed: {e}")
logger.critical(traceback.format_exc())
send_error_notification(e)
if __name__ == "__main__":
main()