acecalisto3 commited on
Commit
7f65bf9
Β·
verified Β·
1 Parent(s): c8ff505

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +391 -245
app.py CHANGED
@@ -1,282 +1,428 @@
 
 
 
 
 
 
 
 
 
 
1
  import json
2
  import os
3
- import re
4
- import time
5
- import logging
6
- import mimetypes
7
- import concurrent.futures
8
- import string
9
- from typing import List, Dict, Optional, Union
10
  from pathlib import Path
11
- from urllib.parse import urlparse
12
 
13
- import requests
14
- import validators
15
- import gradio as gr
16
- import torch
17
- import cachetools
18
- from bs4 import BeautifulSoup
19
- from fake_useragent import UserAgent
20
- from ratelimit import limits, sleep_and_retry
21
 
22
- # Advanced Logging Configuration
23
  logging.basicConfig(
24
  level=logging.INFO,
25
- format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
26
- handlers=[
27
- logging.StreamHandler(),
28
- logging.FileHandler('app_advanced.log', encoding='utf-8')
29
- ]
30
  )
31
  logger = logging.getLogger(__name__)
32
 
33
- class AdvancedURLProcessor:
34
- """Enhanced URL processing with advanced features"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
- def __init__(
37
- self,
38
- timeout: int = 15,
39
- max_retries: int = 3,
40
- concurrent_requests: int = 5,
41
- cache_size: int = 100
42
- ):
43
- self.timeout = timeout
44
- self.max_retries = max_retries
45
- self.concurrent_requests = concurrent_requests
46
- self.ua = UserAgent()
47
 
48
- # Implement multilevel caching
49
- self.url_cache = cachetools.LRUCache(maxsize=cache_size)
50
- self.content_cache = cachetools.TTLCache(maxsize=cache_size, ttl=3600) # 1-hour cache
51
-
52
- self.session = requests.Session()
53
- self.session.headers.update({
54
- 'User-Agent': self.ua.random,
55
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
56
- 'Accept-Language': 'en-US,en;q=0.5',
57
- 'Connection': 'keep-alive'
58
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
- @sleep_and_retry
61
- @limits(calls=10, period=60) # Rate limiting: 10 calls per minute
62
- def validate_url(self, url: str) -> Dict[str, Union[bool, str]]:
63
- """Enhanced URL validation with comprehensive checks"""
64
  try:
65
- # Check cache first
66
- if url in self.url_cache:
67
- return self.url_cache[url]
68
 
69
- # Comprehensive URL validation
70
- result = urlparse(url)
71
- validation_result = {
72
- 'is_valid': False,
73
- 'message': 'Invalid URL',
74
- 'scheme': result.scheme,
75
- 'netloc': result.netloc
76
- }
77
 
78
- if not all([result.scheme, result.netloc]):
79
- validation_result['message'] = 'Missing scheme or network location'
80
- return validation_result
 
81
 
82
- # Use validators for additional checks
83
- if not validators.url(url):
84
- validation_result['message'] = 'URL format validation failed'
85
- return validation_result
 
 
 
86
 
87
- # Perform HEAD request for accessibility
88
- try:
89
- response = self.session.head(
90
- url,
91
- timeout=self.timeout,
92
- allow_redirects=True
93
- )
94
-
95
- validation_result['is_valid'] = response.status_code in [200, 301, 302]
96
- validation_result['status_code'] = response.status_code
97
- validation_result['message'] = f"URL is {'valid' if validation_result['is_valid'] else 'invalid'}"
98
-
99
- except requests.RequestException as e:
100
- validation_result['message'] = f"Connection error: {str(e)}"
101
 
102
- # Cache the result
103
- self.url_cache[url] = validation_result
104
- return validation_result
105
-
106
  except Exception as e:
107
- logger.error(f"Unexpected error validating URL {url}: {e}")
108
- return {
109
- 'is_valid': False,
110
- 'message': f"Unexpected validation error: {str(e)}"
111
- }
112
 
113
- def advanced_text_cleaning(self, text: str) -> str:
114
- """Sophisticated text cleaning and normalization"""
115
- if not text:
116
- return ""
117
-
118
- # Remove control characters
119
- text = re.sub(r'[\x00-\x1F\x7F-\x9F]', '', text)
120
-
121
- # Normalize Unicode characters
122
- text = text.encode('ascii', 'ignore').decode('ascii')
123
-
124
- # Replace multiple whitespaces
125
- text = re.sub(r'\s+', ' ', text)
126
-
127
- # Remove HTML entities
128
- text = re.sub(r'&[a-zA-Z]+;', '', text)
129
-
130
- # Normalize quotation marks
131
- text = text.replace('"', '"').replace('"', '"')
132
- text = text.replace(''', "'").replace(''', "'")
133
-
134
- # Remove excessive punctuation
135
- text = re.sub(r'([.,!?]){2,}', r'\1', text)
136
-
137
- return text.strip()
138
 
139
- @sleep_and_retry
140
- @limits(calls=20, period=60) # Refined rate limiting
141
- def fetch_content(self, url: str) -> Optional[str]:
142
- """Advanced content fetching with multiple safeguards"""
143
- # Check content cache first
144
- if url in self.content_cache:
145
- return self.content_cache[url]
146
 
147
- for attempt in range(self.max_retries):
148
- try:
149
- response = self.session.get(
150
- url,
151
- timeout=self.timeout,
152
- headers={'User-Agent': self.ua.random}
153
- )
154
- response.raise_for_status()
155
-
156
- # Use BeautifulSoup for more robust parsing
157
- soup = BeautifulSoup(response.text, 'html.parser')
158
-
159
- # Remove scripts, styles, comments
160
- for script in soup(["script", "style"]):
161
- script.decompose()
162
-
163
- # Extract clean text
164
- text = soup.get_text(separator=' ')
165
- cleaned_text = self.advanced_text_cleaning(text)
166
-
167
- # Cache the result
168
- self.content_cache[url] = cleaned_text
169
- return cleaned_text
170
-
171
- except requests.RequestException as e:
172
- logger.warning(f"Fetch attempt {attempt + 1} failed for {url}: {e}")
173
- time.sleep(2 ** attempt) # Exponential backoff
174
 
175
- return None
176
-
177
- def create_advanced_interface():
178
- """Create a comprehensive Gradio interface with advanced features"""
179
-
180
- css = """
181
- .container { max-width: 1200px; margin: auto; }
182
- .warning { background-color: #fff3cd; color: #856404; }
183
- .error { background-color: #f8d7da; color: #721c24; }
184
- """
185
-
186
- with gr.Blocks(css=css, title="Advanced Text & URL Processor") as interface:
187
- gr.Markdown("# 🌐 Advanced URL & Text Processing Toolkit")
188
 
189
- with gr.Tab("URL Processing"):
190
- url_input = gr.Textbox(
191
- label="Enter URLs (comma or newline separated)",
192
- lines=5,
193
- placeholder="https://example1.com\nhttps://example2.com"
194
- )
195
 
196
- with gr.Tab("Text Input"):
197
- text_input = gr.Textbox(
198
- label="Raw Text Input",
199
- lines=5,
200
- placeholder="Paste your text here..."
 
 
 
 
201
  )
202
-
203
- process_btn = gr.Button("Process Input", variant="primary")
204
-
205
- output_text = gr.Textbox(label="Processing Results", interactive=False)
206
- output_file = gr.File(label="Processed Output")
207
-
208
- def process_input(urls, text):
209
- try:
210
- processor = AdvancedURLProcessor()
211
- results = []
212
-
213
- # Process URLs
214
- if urls:
215
- url_list = re.split(r'[,\n]', urls)
216
- url_list = [url.strip() for url in url_list if url.strip()]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
 
218
- for url in url_list:
219
- validation = processor.validate_url(url)
220
- if validation.get('is_valid'):
221
- content = processor.fetch_content(url)
222
- if content:
223
- results.append({
224
- 'url': url,
225
- 'content': content,
226
- 'timestamp': time.strftime("%Y-%m-%d %H:%M:%S")
227
- })
228
-
229
- # Process text input
230
- if text:
231
- cleaned_text = processor.advanced_text_cleaning(text)
232
- results.append({
233
- 'source': 'direct_input',
234
- 'content': cleaned_text,
235
- 'timestamp': time.strftime("%Y-%m-%d %H:%M:%S")
236
- })
237
 
238
- # Generate output
239
- if results:
240
- output_path = 'processed_data.json'
241
- with open(output_path, 'w', encoding='utf-8') as f:
242
- json.dump(results, f, ensure_ascii=False, indent=2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
 
244
- summary = f"Processed {len(results)} items successfully!"
245
- return output_path, summary
246
- else:
247
- return None, "No valid content to process."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
 
249
- except Exception as e:
250
- logger.error(f"Processing error: {e}")
251
- return None, f"Error: {str(e)}"
252
-
253
- process_btn.click(
254
- process_input,
255
- inputs=[url_input, text_input],
256
- outputs=[output_file, output_text]
257
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
 
259
- gr.Markdown("""
260
- ### Usage Guidelines
261
- - URL Processing: Enter valid HTTP/HTTPS URLs
262
- - Text Input: Direct text processing
263
- - Advanced cleaning and validation included
264
- """)
265
-
266
- return interface
267
 
268
  def main():
269
- # Configure system settings
270
- mimetypes.init()
271
-
272
- # Create and launch interface
273
- interface = create_advanced_interface()
274
- interface.launch(
275
- share=True,
276
- server_name="0.0.0.0",
277
- server_port=7860,
278
- debug=True
279
- )
 
 
 
 
 
 
 
 
 
 
280
 
281
  if __name__ == "__main__":
282
  main()
 
1
+ """
2
+ Advanced URL & Text Processing Suite - Main Application
3
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
+
5
+ A sophisticated Gradio interface for URL processing, file manipulation, and QR operations.
6
+ Features a modern, responsive UI with real-time feedback and advanced processing capabilities.
7
+ """
8
+
9
+ import gradio as gr
10
+ import logging
11
  import json
12
  import os
13
+ import sys
14
+ from datetime import datetime
 
 
 
 
 
15
  from pathlib import Path
16
+ from typing import Dict, List, Optional, Union, Any, Tuple
17
 
18
+ from url_processor import URLProcessor
19
+ from file_processor import FileProcessor
20
+ from qr_processor import QRProcessor
 
 
 
 
 
21
 
22
+ # Configure logging
23
  logging.basicConfig(
24
  level=logging.INFO,
25
+ format='%(asctime)s.%(msecs)03d [%(levelname)s] %(name)s - %(message)s',
26
+ datefmt='%Y-%m-%d %H:%M:%S'
 
 
 
27
  )
28
  logger = logging.getLogger(__name__)
29
 
30
+ # Modern UI Configuration
31
+ THEME = gr.themes.Soft(
32
+ primary_hue="indigo",
33
+ secondary_hue="blue",
34
+ neutral_hue="slate",
35
+ spacing_size=gr.themes.sizes.spacing_md,
36
+ radius_size=gr.themes.sizes.radius_md,
37
+ text_size=gr.themes.sizes.text_md,
38
+ ).set(
39
+ body_background_fill="*background_fill_secondary",
40
+ button_primary_background_fill="*primary_500",
41
+ button_primary_background_fill_hover="*primary_600",
42
+ button_primary_text_color="white",
43
+ button_primary_border_color="*primary_500",
44
+ button_secondary_background_fill="*secondary_500",
45
+ button_secondary_background_fill_hover="*secondary_600",
46
+ button_secondary_text_color="white",
47
+ button_secondary_border_color="*secondary_500",
48
+ )
49
+
50
+ # Custom CSS for enhanced visual appeal
51
+ CUSTOM_CSS = """
52
+ .container {
53
+ max-width: 1200px !important;
54
+ margin: auto !important;
55
+ padding: 2rem !important;
56
+ }
57
+
58
+ .header {
59
+ text-align: center;
60
+ margin-bottom: 2rem;
61
+ padding: 1rem;
62
+ background: linear-gradient(135deg, #6366f1 0%, #2563eb 100%);
63
+ border-radius: 1rem;
64
+ color: white;
65
+ }
66
+
67
+ .status-bar {
68
+ background: #f8fafc;
69
+ border-radius: 0.5rem;
70
+ padding: 0.5rem;
71
+ margin: 1rem 0;
72
+ border: 1px solid #e2e8f0;
73
+ }
74
+
75
+ .success-message {
76
+ color: #059669;
77
+ background: #ecfdf5;
78
+ border: 1px solid #059669;
79
+ border-radius: 0.5rem;
80
+ padding: 1rem;
81
+ margin: 1rem 0;
82
+ }
83
+
84
+ .error-message {
85
+ color: #dc2626;
86
+ background: #fef2f2;
87
+ border: 1px solid #dc2626;
88
+ border-radius: 0.5rem;
89
+ padding: 1rem;
90
+ margin: 1rem 0;
91
+ }
92
+
93
+ .tab-nav {
94
+ background: #f8fafc;
95
+ border-radius: 0.5rem;
96
+ padding: 0.5rem;
97
+ margin-bottom: 1rem;
98
+ }
99
+
100
+ .tab-nav button {
101
+ transition: all 0.3s ease;
102
+ }
103
+
104
+ .tab-nav button:hover {
105
+ transform: translateY(-1px);
106
+ }
107
+
108
+ .json-editor {
109
+ font-family: 'JetBrains Mono', monospace;
110
+ background: #1e293b;
111
+ color: #e2e8f0;
112
+ border-radius: 0.5rem;
113
+ padding: 1rem;
114
+ }
115
+
116
+ .file-upload {
117
+ border: 2px dashed #e2e8f0;
118
+ border-radius: 1rem;
119
+ padding: 2rem;
120
+ text-align: center;
121
+ transition: all 0.3s ease;
122
+ }
123
+
124
+ .file-upload:hover {
125
+ border-color: #6366f1;
126
+ background: #f8fafc;
127
+ }
128
+
129
+ @keyframes pulse {
130
+ 0% { transform: scale(1); }
131
+ 50% { transform: scale(1.05); }
132
+ 100% { transform: scale(1); }
133
+ }
134
+
135
+ .processing {
136
+ animation: pulse 2s infinite;
137
+ }
138
+ """
139
+
140
+ class AdvancedInterface:
141
+ """Advanced Gradio interface with sophisticated processing capabilities"""
142
 
143
+ def __init__(self):
144
+ """Initialize processors and interface components"""
145
+ self.url_processor = URLProcessor()
146
+ self.file_processor = FileProcessor()
147
+ self.qr_processor = QRProcessor()
148
+ self.processing_history: List[Dict] = []
 
 
 
 
 
149
 
150
+ def process_urls(self, urls: str, mode: str) -> Tuple[str, str, str]:
151
+ """Process URLs with advanced error handling and result formatting"""
152
+ try:
153
+ # Split and clean URLs
154
+ url_list = [url.strip() for url in urls.split('\n') if url.strip()]
155
+
156
+ if not url_list:
157
+ return "", "⚠️ No valid URLs provided", ""
158
+
159
+ # Process URLs
160
+ results = self.url_processor.process_urls(url_list, mode=mode)
161
+
162
+ # Format results
163
+ formatted_results = json.dumps(results, indent=2)
164
+ summary = self._generate_summary(results)
165
+
166
+ # Update history
167
+ self.processing_history.append({
168
+ 'timestamp': datetime.now().isoformat(),
169
+ 'type': 'url_processing',
170
+ 'input_count': len(url_list),
171
+ 'success_count': len([r for r in results if 'error' not in r]),
172
+ 'results': results
173
+ })
174
+
175
+ return formatted_results, f"βœ… Successfully processed {len(url_list)} URLs", summary
176
+
177
+ except Exception as e:
178
+ logger.error(f"URL processing error: {e}", exc_info=True)
179
+ return "", f"❌ Error: {str(e)}", ""
180
 
181
+ def process_file(self, file: gr.File) -> Tuple[str, str, Optional[Path]]:
182
+ """Process uploaded file with comprehensive error handling"""
 
 
183
  try:
184
+ if not file:
185
+ return "", "⚠️ No file provided", None
 
186
 
187
+ results = self.file_processor.process_file(file)
 
 
 
 
 
 
 
188
 
189
+ # Generate output file
190
+ output_path = Path('processed_output.json')
191
+ with open(output_path, 'w') as f:
192
+ json.dump(results, f, indent=2)
193
 
194
+ # Update history
195
+ self.processing_history.append({
196
+ 'timestamp': datetime.now().isoformat(),
197
+ 'type': 'file_processing',
198
+ 'filename': file.name,
199
+ 'results': results
200
+ })
201
 
202
+ return (
203
+ json.dumps(results, indent=2),
204
+ f"βœ… Successfully processed {file.name}",
205
+ output_path
206
+ )
 
 
 
 
 
 
 
 
 
207
 
 
 
 
 
208
  except Exception as e:
209
+ logger.error(f"File processing error: {e}", exc_info=True)
210
+ return "", f"❌ Error: {str(e)}", None
 
 
 
211
 
212
+ def generate_qr(self, data: str, size: int = 10) -> Tuple[Optional[Path], str]:
213
+ """Generate QR code with advanced options"""
214
+ try:
215
+ if not data:
216
+ return None, "⚠️ No data provided"
217
+
218
+ result = self.qr_processor.generate_qr_code(data, size=size)
219
+
220
+ if 'error' in result:
221
+ return None, f"❌ Error: {result['error']}"
222
+
223
+ # Update history
224
+ self.processing_history.append({
225
+ 'timestamp': datetime.now().isoformat(),
226
+ 'type': 'qr_generation',
227
+ 'data_length': len(data),
228
+ 'output_path': result['output_path']
229
+ })
230
+
231
+ return result['output_path'], "βœ… QR code generated successfully"
232
+
233
+ except Exception as e:
234
+ logger.error(f"QR generation error: {e}", exc_info=True)
235
+ return None, f"❌ Error: {str(e)}"
 
236
 
237
+ def _generate_summary(self, results: List[Dict]) -> str:
238
+ """Generate a human-readable summary of processing results"""
239
+ success_count = len([r for r in results if 'error' not in r])
240
+ error_count = len(results) - success_count
 
 
 
241
 
242
+ summary = [
243
+ "πŸ“Š Processing Summary",
244
+ f"Total URLs: {len(results)}",
245
+ f"Successful: {success_count}",
246
+ f"Failed: {error_count}",
247
+ "",
248
+ "πŸ” Details:"
249
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
 
251
+ for result in results:
252
+ if 'error' in result:
253
+ summary.append(f"❌ {result['url']}: {result['error']}")
254
+ else:
255
+ summary.append(f"βœ… {result['url']}: Successfully processed")
 
 
 
 
 
 
 
 
256
 
257
+ return '\n'.join(summary)
258
+
259
+ def create_interface(self) -> gr.Blocks:
260
+ """Create a sophisticated Gradio interface"""
 
 
261
 
262
+ with gr.Blocks(theme=THEME, css=CUSTOM_CSS) as interface:
263
+ # Header
264
+ gr.Markdown(
265
+ """
266
+ <div class="header">
267
+ <h1>🌐 Advanced URL & Text Processing Suite</h1>
268
+ <p>Enterprise-grade toolkit for URL processing, file manipulation, and QR operations</p>
269
+ </div>
270
+ """
271
  )
272
+
273
+ # Main tabs
274
+ with gr.Tabs(elem_classes="tab-nav") as tabs:
275
+ # URL Processing Tab
276
+ with gr.Tab("πŸ”— URL Processing", id=1):
277
+ with gr.Row():
278
+ with gr.Column(scale=2):
279
+ url_input = gr.Textbox(
280
+ label="URLs",
281
+ placeholder="Enter URLs (one per line)",
282
+ lines=5
283
+ )
284
+ mode = gr.Radio(
285
+ choices=["basic", "interactive", "deep"],
286
+ value="basic",
287
+ label="Processing Mode"
288
+ )
289
+ process_btn = gr.Button("πŸš€ Process URLs", variant="primary")
290
+
291
+ with gr.Column(scale=1):
292
+ gr.Markdown(
293
+ """
294
+ ### πŸ“ Instructions
295
+ 1. Enter URLs (one per line)
296
+ 2. Select processing mode:
297
+ - Basic: Simple content fetch
298
+ - Interactive: Handle dynamic content
299
+ - Deep: Follow links and analyze deeply
300
+ 3. Click Process to start
301
+ """
302
+ )
303
 
304
+ with gr.Row():
305
+ status_output = gr.Textbox(label="Status", interactive=False)
306
+ clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary")
307
+
308
+ with gr.Accordion("Results", open=False):
309
+ json_output = gr.JSON(label="Detailed Results")
310
+ summary_output = gr.Textbox(
311
+ label="Summary",
312
+ interactive=False,
313
+ lines=10
314
+ )
 
 
 
 
 
 
 
 
315
 
316
+ # File Processing Tab
317
+ with gr.Tab("πŸ“ File Processing", id=2):
318
+ with gr.Row():
319
+ with gr.Column(scale=2):
320
+ file_input = gr.File(
321
+ label="Upload File",
322
+ file_types=[".txt", ".pdf", ".zip", ".tar.gz"]
323
+ )
324
+ process_file_btn = gr.Button("πŸ“₯ Process File", variant="primary")
325
+
326
+ with gr.Column(scale=1):
327
+ gr.Markdown(
328
+ """
329
+ ### πŸ“ Supported Formats
330
+ - Text files (.txt)
331
+ - PDF documents (.pdf)
332
+ - Archives (.zip, .tar.gz)
333
+ - Images (.jpg, .png)
334
+ - And more...
335
+ """
336
+ )
337
 
338
+ with gr.Row():
339
+ file_status = gr.Textbox(label="Status", interactive=False)
340
+ file_output = gr.File(label="Processed Output")
341
+
342
+ with gr.Accordion("Results", open=False):
343
+ file_json_output = gr.JSON(label="Detailed Results")
344
+
345
+ # QR Code Tab
346
+ with gr.Tab("πŸ“± QR Code", id=3):
347
+ with gr.Row():
348
+ with gr.Column(scale=2):
349
+ qr_input = gr.Textbox(
350
+ label="Data",
351
+ placeholder="Enter data to encode",
352
+ lines=3
353
+ )
354
+ qr_size = gr.Slider(
355
+ minimum=5,
356
+ maximum=50,
357
+ value=10,
358
+ step=1,
359
+ label="QR Code Size"
360
+ )
361
+ generate_qr_btn = gr.Button("✨ Generate QR", variant="primary")
362
+
363
+ with gr.Column(scale=1):
364
+ qr_output = gr.Image(label="Generated QR Code")
365
+ qr_status = gr.Textbox(label="Status", interactive=False)
366
 
367
+ # Footer
368
+ gr.Markdown(
369
+ """
370
+ <div style="text-align: center; margin-top: 2rem; padding: 1rem; background: #f8fafc; border-radius: 0.5rem;">
371
+ <p>Made with ❀️ by Advanced URL Processing Team</p>
372
+ <p style="font-size: 0.8rem;">Version 1.0.0</p>
373
+ </div>
374
+ """
375
+ )
376
+
377
+ # Event handlers
378
+ process_btn.click(
379
+ fn=self.process_urls,
380
+ inputs=[url_input, mode],
381
+ outputs=[json_output, status_output, summary_output]
382
+ )
383
+
384
+ clear_btn.click(
385
+ fn=lambda: ("", "", ""),
386
+ inputs=[],
387
+ outputs=[url_input, status_output, summary_output]
388
+ )
389
+
390
+ process_file_btn.click(
391
+ fn=self.process_file,
392
+ inputs=[file_input],
393
+ outputs=[file_json_output, file_status, file_output]
394
+ )
395
+
396
+ generate_qr_btn.click(
397
+ fn=self.generate_qr,
398
+ inputs=[qr_input, qr_size],
399
+ outputs=[qr_output, qr_status]
400
+ )
401
 
402
+ return interface
 
 
 
 
 
 
 
403
 
404
  def main():
405
+ """Main entry point"""
406
+ try:
407
+ # Initialize interface
408
+ app = AdvancedInterface()
409
+ interface = app.create_interface()
410
+
411
+ # Launch with optimal settings
412
+ interface.launch(
413
+ server_name="0.0.0.0",
414
+ server_port=8000,
415
+ share=False,
416
+ debug=True,
417
+ enable_queue=True,
418
+ max_threads=40,
419
+ auth=None, # Add authentication if needed
420
+ ssl_keyfile=None, # Add SSL if needed
421
+ ssl_certfile=None
422
+ )
423
+ except Exception as e:
424
+ logger.error(f"Application startup error: {e}", exc_info=True)
425
+ sys.exit(1)
426
 
427
  if __name__ == "__main__":
428
  main()