acecalisto3 commited on
Commit
4da78ca
·
verified ·
1 Parent(s): 15fb404

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +64 -199
app.py CHANGED
@@ -13,7 +13,6 @@ from typing import List, Dict, Tuple, Union, Optional
13
  import requests
14
  import validators
15
  import gradio as gr
16
- from diskcache import Cache
17
  from bs4 import BeautifulSoup
18
  from fake_useragent import UserAgent
19
  from cleantext import clean
@@ -73,6 +72,7 @@ class URLProcessor:
73
  try:
74
  if not validators.url(url):
75
  return {'is_valid': False, 'message': 'Invalid URL format'}
 
76
  response = self.session.head(url, timeout=self.timeout)
77
  response.raise_for_status()
78
  return {'is_valid': True, 'message': 'URL is valid and accessible'}
@@ -85,9 +85,11 @@ class URLProcessor:
85
  # Google Drive document handling
86
  if 'drive.google.com' in url:
87
  return self._handle_google_drive(url)
 
88
  # Google Calendar ICS handling
89
  if 'calendar.google.com' in url and 'ical' in url:
90
  return self._handle_google_calendar(url)
 
91
  # Standard HTML processing
92
  return self._fetch_html_content(url)
93
  except Exception as e:
@@ -96,14 +98,15 @@ class URLProcessor:
96
 
97
  def _handle_google_drive(self, url: str) -> Optional[Dict]:
98
  """Process Google Drive file links"""
99
- try:
100
- file_id = re.search(r'/file/d/([a-zA-Z0-9_-]+)', url)
101
  if not file_id:
102
  logger.error(f"Invalid Google Drive URL: {url}")
103
  return None
 
104
  direct_url = f"https://drive.google.com/uc?export=download&id={file_id.group(1)}"
105
  response = self.session.get(direct_url, timeout=self.timeout)
106
  response.raise_for_status()
 
107
  return {
108
  'content': response.text,
109
  'content_type': response.headers.get('Content-Type', ''),
@@ -132,15 +135,20 @@ class URLProcessor:
132
  try:
133
  response = self.session.get(url, timeout=self.timeout)
134
  response.raise_for_status()
 
135
  soup = BeautifulSoup(response.text, 'html.parser')
 
136
  # Remove unwanted elements
137
  for element in soup(['script', 'style', 'nav', 'footer', 'header', 'meta', 'link']):
138
  element.decompose()
 
139
  # Extract main content
140
  main_content = soup.find('main') or soup.find('article') or soup.body
 
141
  # Clean and structure content
142
  text_content = main_content.get_text(separator='\n', strip=True)
143
  cleaned_content = self.advanced_text_cleaning(text_content)
 
144
  return {
145
  'content': cleaned_content,
146
  'content_type': response.headers.get('Content-Type', ''),
@@ -207,14 +215,17 @@ class FileProcessor:
207
  def _process_single_file(self, file) -> List[Dict]:
208
  try:
209
  file_stat = os.stat(file.name)
 
210
  # For very large files, read in chunks and summarize
211
  if file_stat.st_size > 100 * 1024 * 1024: # 100MB
212
  logger.info(f"Processing large file: {file.name} ({file_stat.st_size} bytes)")
213
- # Read first and last 1MB for extremely large files
 
214
  content = ""
215
  with open(file.name, 'r', encoding='utf-8', errors='ignore') as f:
216
  content = f.read(1 * 1024 * 1024) # First 1MB
217
  content += "\n...[Content truncated due to large file size]...\n"
 
218
  # Seek to the last 1MB
219
  f.seek(max(0, file_stat.st_size - 1 * 1024 * 1024))
220
  content += f.read() # Last 1MB
@@ -222,6 +233,7 @@ class FileProcessor:
222
  # Regular file processing
223
  with open(file.name, 'r', encoding='utf-8', errors='ignore') as f:
224
  content = f.read()
 
225
  return [{
226
  'source': 'file',
227
  'filename': os.path.basename(file.name),
@@ -236,7 +248,6 @@ class FileProcessor:
236
  logger.error(f"File processing error: {e}")
237
  return []
238
 
239
-
240
  def generate_qr(json_data):
241
  """Generate QR code from JSON data and return the file path."""
242
  try:
@@ -248,7 +259,7 @@ def generate_qr(json_data):
248
  )
249
  qr.add_data(json_data)
250
  qr.make(fit=True)
251
-
252
  img = qr.make_image(fill_color="black", back_color="white")
253
  temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
254
  img.save(temp_file.name)
@@ -256,6 +267,7 @@ def generate_qr(json_data):
256
  except Exception as e:
257
  # If the data is too large for a QR code
258
  logger.error(f"QR generation error: {e}")
 
259
  # Create a simple QR with error message
260
  qr = qrcode.QRCode(
261
  version=1,
@@ -265,211 +277,54 @@ def generate_qr(json_data):
265
  )
266
  qr.add_data("Error: Data too large for QR code")
267
  qr.make(fit=True)
268
-
269
  img = qr.make_image(fill_color="black", back_color="white")
270
  temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
271
  img.save(temp_file.name)
272
  return temp_file.name
273
 
274
-
275
  def create_interface():
276
- """Create a comprehensive Gradio interface with advanced features and styling"""
 
277
  css = """
278
- body {
279
- font-family: 'Inter', sans-serif;
280
- background: linear-gradient(to bottom, #08041C, #030712); /* Dark cosmic background */
281
- color: #ffffff;
282
- }
283
- .container {
284
- max-width: 1200px;
285
- margin: auto;
286
- background-color: rgba(255, 255, 255, 0.06);
287
- backdrop-filter: blur(12px);
288
- border: 1px solid rgba(255, 255, 255, 0.1);
289
- border-radius: 1rem;
290
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
291
- padding: 2rem;
292
- }
293
- h1 {
294
- color: #00FF00;
295
- text-align: center;
296
- text-shadow: 0 0 10px rgba(0, 255, 0, 0.8);
297
- }
298
- h2, h3, h4 {
299
- color: #FF9900;
300
- text-shadow: 0 0 10px rgba(255, 153, 0, 0.8);
301
- }
302
- .tab {
303
- background-color: rgba(255, 255, 255, 0.06);
304
- backdrop-filter: blur(12px);
305
- border: 1px solid rgba(255, 255, 255, 0.1);
306
- border-radius: 0.75rem;
307
- margin-bottom: 1rem;
308
- padding: 1.5rem;
309
- }
310
- .tab:hover {
311
- background-color: rgba(255, 255, 255, 0.1);
312
- }
313
- .warning {
314
- background-color: #fff3cd;
315
- color: #856404;
316
- border-radius: 0.5rem;
317
- padding: 1rem;
318
- margin-bottom: 1rem;
319
- }
320
- .error {
321
- background-color: #f8d7da;
322
- color: #721c24;
323
- border-radius: 0.5rem;
324
- padding: 1rem;
325
- margin-bottom: 1rem;
326
- }
327
- input[type="text"], input[type="file"] {
328
- width: 100%;
329
- padding: 0.75rem;
330
- border-radius: 0.5rem;
331
- background-color: rgba(0, 0, 0, 0.2);
332
- color: #ffffff;
333
- border: 1px solid #4a5568;
334
- font-size: 1rem;
335
- transition: border-color 0.3s ease;
336
- }
337
- input[type="text"]:focus, input[type="file"]:focus {
338
- outline: none;
339
- border-color: #00FF00;
340
- box-shadow: 0 0 5px rgba(0, 255, 0, 0.7);
341
- }
342
- .btn-primary {
343
- padding: 0.75rem 1.5rem;
344
- border-radius: 1.5rem;
345
- font-weight: 600;
346
- cursor: pointer;
347
- transition: transform 0.2s ease, box-shadow 0.2s ease, background-image 0.3s;
348
- background-image: linear-gradient(to right, #00FF00, #00A300);
349
- color: #000000;
350
- border: none;
351
- box-shadow: 0 0 8px rgba(0, 255, 0, 0.5);
352
- }
353
- .btn-primary:hover {
354
- transform: scale(1.05);
355
- box-shadow: 0 0 12px rgba(0, 255, 0, 0.7);
356
- background-image: linear-gradient(to right, #00A300, #007D00);
357
- }
358
- .btn-secondary {
359
- padding: 0.75rem 1.5rem;
360
- border-radius: 1.5rem;
361
- font-weight: 600;
362
- cursor: pointer;
363
- transition: transform 0.2s ease, box-shadow 0.2s ease, background-image 0.3s;
364
- background-image: linear-gradient(to right, #FF9900, #FF6600);
365
- color: #000000;
366
- border: none;
367
- box-shadow: 0 0 8px rgba(255, 153, 0, 0.5);
368
- }
369
- .btn-secondary:hover {
370
- transform: scale(1.05);
371
- box-shadow: 0 0 12px rgba(255, 153, 0, 0.7);
372
- background-image: linear-gradient(to right, #FF6600, #CC4700);
373
- }
374
- textarea {
375
- width: 100%;
376
- padding: 0.75rem;
377
- border-radius: 0.5rem;
378
- background-color: rgba(0, 0, 0, 0.2);
379
- color: #ffffff;
380
- border: 1px solid #4a5568;
381
- font-size: 1rem;
382
- transition: border-color 0.3s ease;
383
- min-height: 8rem;
384
- }
385
- textarea:focus {
386
- outline: none;
387
- border-color: #00FF00;
388
- box-shadow: 0 0 5px rgba(0, 255, 0, 0.7);
389
- }
390
- .output-box {
391
- background-color: rgba(0, 0, 0, 0.2);
392
- border: 1px solid #4a5568;
393
- border-radius: 0.5rem;
394
- padding: 1rem;
395
- overflow-x: auto;
396
- color: #ffffff;
397
- font-size: 1rem;
398
- white-space: pre-wrap;
399
- }
400
- #json-editor {
401
- background-color: rgba(0, 0, 0, 0.2);
402
- color: #ffffff;
403
- border: 1px solid #4a5568;
404
- border-radius: 0.5rem;
405
- padding: 1rem;
406
- font-size: 1rem;
407
- min-height: 20rem;
408
- }
409
- #json-editor:focus {
410
- outline: none;
411
- border-color: #00FF00;
412
- box-shadow: 0 0 5px rgba(0, 255, 0, 0.7);
413
- }
414
- #url-input {
415
- background-color: rgba(0, 0, 0, 0.2);
416
- color: #ffffff;
417
- border: 1px solid #4a5568;
418
- border-radius: 0.5rem;
419
- padding: 1rem;
420
- font-size: 1rem;
421
- min-height: 8rem;
422
- }
423
- #url-input:focus {
424
- outline: none;
425
- border-color: #00FF00;
426
- box-shadow: 0 0 5px rgba(0, 255, 0, 0.7);
427
- }
428
- #output-text{
429
- background-color: rgba(0, 0, 0, 0.2);
430
- color: #ffffff;
431
- border: 1px solid #4a5568;
432
- border-radius: 0.5rem;
433
- padding: 1rem;
434
- font-size: 1rem;
435
- }
436
  """
 
437
  with gr.Blocks(css=css, title="Advanced Text & URL Processor") as interface:
438
  gr.Markdown("# 🌐 Advanced URL & Text Processing Toolkit")
439
 
440
- with gr.Tab("URL Processing") as url_tab:
441
  url_input = gr.Textbox(
442
  label="Enter URLs (comma or newline separated)",
443
  lines=5,
444
- placeholder="https://example1.com\nhttps://example2.com",
445
- interactive=True,
446
- elem_id="url-input"
447
  )
448
 
449
- with gr.Tab("File Input") as file_tab:
450
  file_input = gr.File(
451
  label="Upload text file or ZIP archive",
452
  file_types=[".txt", ".zip", ".md", ".csv", ".json", ".xml"]
453
  )
454
 
455
- with gr.Tab("Text Input") as text_tab:
456
  text_input = gr.Textbox(
457
  label="Raw Text Input",
458
  lines=5,
459
- placeholder="Paste your text here...",
460
- interactive=True
461
  )
462
 
463
- with gr.Tab("JSON Editor") as json_tab:
464
  json_editor = gr.Textbox(
465
  label="JSON Editor",
466
  lines=20,
467
  placeholder="View and edit your JSON data here...",
468
  interactive=True,
469
- elem_id="json-editor"
470
  )
471
 
472
- with gr.Tab("Scratchpad") as scratchpad_tab:
473
  scratchpad = gr.Textbox(
474
  label="Scratchpad",
475
  lines=10,
@@ -480,7 +335,7 @@ def create_interface():
480
  process_btn = gr.Button("Process Input", variant="primary")
481
  qr_btn = gr.Button("Generate QR Code", variant="secondary")
482
 
483
- output_text = gr.Textbox(label="Processing Results", interactive=False, elem_id="output-text")
484
  output_file = gr.File(label="Processed Output")
485
  qr_output = gr.Image(label="QR Code", type="filepath") # To display the generated QR code
486
 
@@ -490,10 +345,11 @@ def create_interface():
490
  processor = URLProcessor()
491
  file_processor = FileProcessor()
492
  results = []
493
- # Process URLs
494
- if urls:
495
  url_list = re.split(r'[,\n]', urls)
496
  url_list = [url.strip() for url in url_list if url.strip()]
 
497
  for url in url_list:
498
  validation = processor.validate_url(url)
499
  if validation.get('is_valid'):
@@ -505,9 +361,11 @@ def create_interface():
505
  'content': content,
506
  'timestamp': datetime.now().isoformat()
507
  })
 
508
  # Process files
509
  if file:
510
  results.extend(file_processor.process_file(file))
 
511
  # Process text input
512
  if text:
513
  cleaned_text = processor.advanced_text_cleaning(text)
@@ -516,54 +374,62 @@ def create_interface():
516
  'content': cleaned_text,
517
  'timestamp': datetime.now().isoformat()
518
  })
 
519
  # Generate output
520
  if results:
521
  output_dir = Path('output') / datetime.now().strftime('%Y-%m-%d')
522
  output_dir.mkdir(parents=True, exist_ok=True)
523
  output_path = output_dir / f'processed_{int(time.time())}.json'
 
524
  with open(output_path, 'w', encoding='utf-8') as f:
525
  json.dump(results, f, ensure_ascii=False, indent=2)
 
526
  summary = f"Processed {len(results)} items successfully!"
527
  json_data = json.dumps(results, indent=2) # Prepare JSON for QR code
528
  return str(output_path), summary, json_data # Return JSON for editor
529
  else:
530
  return None, "No valid content to process.", ""
 
531
  except Exception as e:
532
  logger.error(f"Processing error: {e}")
533
  return None, f"Error: {str(e)}", ""
534
 
535
  def generate_qr_code(json_data):
536
- """Generate QR code from JSON data."""
537
- if not json_data:
538
- return "No data to encode."
539
- qr_file = generate_qr(json_data)
540
- return qr_file
541
 
542
  process_btn.click(
543
  process_all_inputs,
544
  inputs=[url_input, file_input, text_input, scratchpad],
545
- outputs=[output_file, output_text, json_editor]
 
 
 
 
 
 
546
  )
547
- qr_btn.click(generate_qr_code, inputs=[json_editor], outputs=[qr_output])
548
 
549
  gr.Markdown("""
550
- ### Usage Guidelines
551
- - **URL Processing**: Enter valid HTTP/HTTPS URLs, separated by commas or newlines.
552
- - **File Input**: Upload text files or ZIP archives containing text files.
553
- - **Text Input**: Paste text directly for processing.
554
- - **JSON Editor**: View the processed data in JSON format. This is automatically updated after processing.
555
- - **Scratchpad**: Use this area for temporary notes or text snippets.
556
- - Click "Process Input" to analyze the data. The results will be available for download and in the JSON Editor.
557
- - Click "Generate QR Code" to create a QR code from the JSON data.
558
- """)
559
  return interface
560
 
561
-
562
  def main():
563
  # Configure system settings
564
  mimetypes.init()
 
565
  # Create and launch interface
566
  interface = create_interface()
 
567
  # Launch with proper configuration
568
  interface.launch(
569
  server_name="0.0.0.0",
@@ -574,6 +440,5 @@ def main():
574
  debug=True
575
  )
576
 
577
-
578
  if __name__ == "__main__":
579
  main()
 
13
  import requests
14
  import validators
15
  import gradio as gr
 
16
  from bs4 import BeautifulSoup
17
  from fake_useragent import UserAgent
18
  from cleantext import clean
 
72
  try:
73
  if not validators.url(url):
74
  return {'is_valid': False, 'message': 'Invalid URL format'}
75
+
76
  response = self.session.head(url, timeout=self.timeout)
77
  response.raise_for_status()
78
  return {'is_valid': True, 'message': 'URL is valid and accessible'}
 
85
  # Google Drive document handling
86
  if 'drive.google.com' in url:
87
  return self._handle_google_drive(url)
88
+
89
  # Google Calendar ICS handling
90
  if 'calendar.google.com' in url and 'ical' in url:
91
  return self._handle_google_calendar(url)
92
+
93
  # Standard HTML processing
94
  return self._fetch_html_content(url)
95
  except Exception as e:
 
98
 
99
  def _handle_google_drive(self, url: str) -> Optional[Dict]:
100
  """Process Google Drive file links"""
101
+ try: file_id = re.search(r'/file/d/([a-zA-Z0-9_-]+)', url)
 
102
  if not file_id:
103
  logger.error(f"Invalid Google Drive URL: {url}")
104
  return None
105
+
106
  direct_url = f"https://drive.google.com/uc?export=download&id={file_id.group(1)}"
107
  response = self.session.get(direct_url, timeout=self.timeout)
108
  response.raise_for_status()
109
+
110
  return {
111
  'content': response.text,
112
  'content_type': response.headers.get('Content-Type', ''),
 
135
  try:
136
  response = self.session.get(url, timeout=self.timeout)
137
  response.raise_for_status()
138
+
139
  soup = BeautifulSoup(response.text, 'html.parser')
140
+
141
  # Remove unwanted elements
142
  for element in soup(['script', 'style', 'nav', 'footer', 'header', 'meta', 'link']):
143
  element.decompose()
144
+
145
  # Extract main content
146
  main_content = soup.find('main') or soup.find('article') or soup.body
147
+
148
  # Clean and structure content
149
  text_content = main_content.get_text(separator='\n', strip=True)
150
  cleaned_content = self.advanced_text_cleaning(text_content)
151
+
152
  return {
153
  'content': cleaned_content,
154
  'content_type': response.headers.get('Content-Type', ''),
 
215
  def _process_single_file(self, file) -> List[Dict]:
216
  try:
217
  file_stat = os.stat(file.name)
218
+
219
  # For very large files, read in chunks and summarize
220
  if file_stat.st_size > 100 * 1024 * 1024: # 100MB
221
  logger.info(f"Processing large file: {file.name} ({file_stat.st_size} bytes)")
222
+
223
+ # Read first and last 1MB for extremely large files
224
  content = ""
225
  with open(file.name, 'r', encoding='utf-8', errors='ignore') as f:
226
  content = f.read(1 * 1024 * 1024) # First 1MB
227
  content += "\n...[Content truncated due to large file size]...\n"
228
+
229
  # Seek to the last 1MB
230
  f.seek(max(0, file_stat.st_size - 1 * 1024 * 1024))
231
  content += f.read() # Last 1MB
 
233
  # Regular file processing
234
  with open(file.name, 'r', encoding='utf-8', errors='ignore') as f:
235
  content = f.read()
236
+
237
  return [{
238
  'source': 'file',
239
  'filename': os.path.basename(file.name),
 
248
  logger.error(f"File processing error: {e}")
249
  return []
250
 
 
251
  def generate_qr(json_data):
252
  """Generate QR code from JSON data and return the file path."""
253
  try:
 
259
  )
260
  qr.add_data(json_data)
261
  qr.make(fit=True)
262
+
263
  img = qr.make_image(fill_color="black", back_color="white")
264
  temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
265
  img.save(temp_file.name)
 
267
  except Exception as e:
268
  # If the data is too large for a QR code
269
  logger.error(f"QR generation error: {e}")
270
+
271
  # Create a simple QR with error message
272
  qr = qrcode.QRCode(
273
  version=1,
 
277
  )
278
  qr.add_data("Error: Data too large for QR code")
279
  qr.make(fit=True)
280
+
281
  img = qr.make_image(fill_color="black", back_color="white")
282
  temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
283
  img.save(temp_file.name)
284
  return temp_file.name
285
 
 
286
  def create_interface():
287
+ """Create a comprehensive Gradio interface with advanced features"""
288
+
289
  css = """
290
+ .container { max-width: 1200px; margin: auto; }
291
+ .warning { background-color: #fff3cd; color: #856404; }
292
+ .error { background-color: #f8d7da; color: #721c24; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  """
294
+
295
  with gr.Blocks(css=css, title="Advanced Text & URL Processor") as interface:
296
  gr.Markdown("# 🌐 Advanced URL & Text Processing Toolkit")
297
 
298
+ with gr.Tab("URL Processing"):
299
  url_input = gr.Textbox(
300
  label="Enter URLs (comma or newline separated)",
301
  lines=5,
302
+ placeholder="https://example1.com\nhttps://example2.com"
 
 
303
  )
304
 
305
+ with gr.Tab("File Input"):
306
  file_input = gr.File(
307
  label="Upload text file or ZIP archive",
308
  file_types=[".txt", ".zip", ".md", ".csv", ".json", ".xml"]
309
  )
310
 
311
+ with gr.Tab("Text Input"):
312
  text_input = gr.Textbox(
313
  label="Raw Text Input",
314
  lines=5,
315
+ placeholder="Paste your text here..."
 
316
  )
317
 
318
+ with gr.Tab("JSON Editor"):
319
  json_editor = gr.Textbox(
320
  label="JSON Editor",
321
  lines=20,
322
  placeholder="View and edit your JSON data here...",
323
  interactive=True,
324
+ elem_id="json-editor" # Optional: for custom styling
325
  )
326
 
327
+ with gr.Tab("Scratchpad"):
328
  scratchpad = gr.Textbox(
329
  label="Scratchpad",
330
  lines=10,
 
335
  process_btn = gr.Button("Process Input", variant="primary")
336
  qr_btn = gr.Button("Generate QR Code", variant="secondary")
337
 
338
+ output_text = gr.Textbox(label="Processing Results", interactive=False)
339
  output_file = gr.File(label="Processed Output")
340
  qr_output = gr.Image(label="QR Code", type="filepath") # To display the generated QR code
341
 
 
345
  processor = URLProcessor()
346
  file_processor = FileProcessor()
347
  results = []
348
+
349
+ # Process URLsif urls:
350
  url_list = re.split(r'[,\n]', urls)
351
  url_list = [url.strip() for url in url_list if url.strip()]
352
+
353
  for url in url_list:
354
  validation = processor.validate_url(url)
355
  if validation.get('is_valid'):
 
361
  'content': content,
362
  'timestamp': datetime.now().isoformat()
363
  })
364
+
365
  # Process files
366
  if file:
367
  results.extend(file_processor.process_file(file))
368
+
369
  # Process text input
370
  if text:
371
  cleaned_text = processor.advanced_text_cleaning(text)
 
374
  'content': cleaned_text,
375
  'timestamp': datetime.now().isoformat()
376
  })
377
+
378
  # Generate output
379
  if results:
380
  output_dir = Path('output') / datetime.now().strftime('%Y-%m-%d')
381
  output_dir.mkdir(parents=True, exist_ok=True)
382
  output_path = output_dir / f'processed_{int(time.time())}.json'
383
+
384
  with open(output_path, 'w', encoding='utf-8') as f:
385
  json.dump(results, f, ensure_ascii=False, indent=2)
386
+
387
  summary = f"Processed {len(results)} items successfully!"
388
  json_data = json.dumps(results, indent=2) # Prepare JSON for QR code
389
  return str(output_path), summary, json_data # Return JSON for editor
390
  else:
391
  return None, "No valid content to process.", ""
392
+
393
  except Exception as e:
394
  logger.error(f"Processing error: {e}")
395
  return None, f"Error: {str(e)}", ""
396
 
397
  def generate_qr_code(json_data):
398
+ """Generate QR code from JSON data and return the file path."""
399
+ if json_data:
400
+ return generate_qr(json_data)
401
+ return None
 
402
 
403
  process_btn.click(
404
  process_all_inputs,
405
  inputs=[url_input, file_input, text_input, scratchpad],
406
+ outputs=[output_file, output_text, json_editor] # Update outputs to include JSON editor
407
+ )
408
+
409
+ qr_btn.click(
410
+ generate_qr_code,
411
+ inputs=json_editor,
412
+ outputs=qr_output
413
  )
 
414
 
415
  gr.Markdown("""
416
+ ### Usage Guidelines
417
+ - **URL Processing**: Enter valid HTTP/HTTPS URLs
418
+ - **File Input**: Upload text files or ZIP archives
419
+ - **Text Input**: Direct text processing
420
+ - **JSON Editor**: View and edit your JSON data
421
+ - **Scratchpad**: Quick notes or text collections
422
+ - Advanced cleaning and validation included
423
+ """)
 
424
  return interface
425
 
 
426
  def main():
427
  # Configure system settings
428
  mimetypes.init()
429
+
430
  # Create and launch interface
431
  interface = create_interface()
432
+
433
  # Launch with proper configuration
434
  interface.launch(
435
  server_name="0.0.0.0",
 
440
  debug=True
441
  )
442
 
 
443
  if __name__ == "__main__":
444
  main()