Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -237,326 +237,326 @@ class FileProcessor:
|
|
237 |
return []
|
238 |
|
239 |
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
)
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
img.save(temp_file.name)
|
255 |
-
return temp_file.name
|
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,
|
262 |
-
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
263 |
-
box_size=10,
|
264 |
-
border=4,
|
265 |
)
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
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,
|
476 |
-
placeholder="Quick notes or text collections...",
|
477 |
-
interactive=True
|
478 |
-
)
|
479 |
-
|
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 |
-
|
487 |
-
def process_all_inputs(urls, file, text, notes):
|
488 |
-
"""Process all input types with progress tracking"""
|
489 |
-
try:
|
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'):
|
500 |
-
content = processor.fetch_content(url)
|
501 |
-
if content:
|
502 |
-
results.append({
|
503 |
-
'source': 'url',
|
504 |
-
'url': url,
|
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)
|
514 |
-
results.append({
|
515 |
-
'source': 'direct_input',
|
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 |
-
|
548 |
-
|
549 |
-
gr.
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
560 |
|
561 |
|
562 |
def main():
|
@@ -576,4 +576,4 @@ def main():
|
|
576 |
|
577 |
|
578 |
if __name__ == "__main__":
|
579 |
-
main()
|
|
|
237 |
return []
|
238 |
|
239 |
|
240 |
+
def generate_qr(json_data):
|
241 |
+
"""Generate QR code from JSON data and return the file path."""
|
242 |
+
try:
|
243 |
+
# Try first with automatic version selection
|
244 |
+
qr = qrcode.QRCode(
|
245 |
+
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
246 |
+
box_size=10,
|
247 |
+
border=4,
|
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)
|
255 |
+
return temp_file.name
|
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,
|
262 |
+
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
263 |
+
box_size=10,
|
264 |
+
border=4,
|
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,
|
476 |
+
placeholder="Quick notes or text collections...",
|
477 |
+
interactive=True
|
478 |
+
)
|
479 |
+
|
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 |
+
|
487 |
+
def process_all_inputs(urls, file, text, notes):
|
488 |
+
"""Process all input types with progress tracking"""
|
489 |
+
try:
|
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'):
|
500 |
+
content = processor.fetch_content(url)
|
501 |
+
if content:
|
502 |
+
results.append({
|
503 |
+
'source': 'url',
|
504 |
+
'url': url,
|
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)
|
514 |
+
results.append({
|
515 |
+
'source': 'direct_input',
|
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():
|
|
|
576 |
|
577 |
|
578 |
if __name__ == "__main__":
|
579 |
+
main()
|