Spaces:
Running
Running
Add shareable URL links (?url= param), JS-site detection, fix examples
Browse files
app.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
"""HuggingFace Space for AI text detection using adaptive-classifier."""
|
| 2 |
|
| 3 |
import re
|
|
|
|
| 4 |
import urllib.request
|
| 5 |
from html.parser import HTMLParser
|
| 6 |
|
|
@@ -365,22 +366,38 @@ def detect_text(text: str) -> dict:
|
|
| 365 |
return {label: round(score, 4) for label, score in predictions}
|
| 366 |
|
| 367 |
|
| 368 |
-
|
|
|
|
|
|
|
|
|
|
| 369 |
"""Fetch a URL and classify its text content."""
|
| 370 |
if not url or not url.strip():
|
| 371 |
-
return _error_label("Please enter a URL"), ""
|
| 372 |
try:
|
| 373 |
text = fetch_url(url)
|
| 374 |
except Exception as e:
|
| 375 |
-
return _error_label(f"Could not fetch URL: {e}"), ""
|
| 376 |
-
|
| 377 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 378 |
words = text.split()
|
| 379 |
if len(words) > 2000:
|
| 380 |
text = " ".join(words[:2000])
|
| 381 |
result = detect_text(text)
|
| 382 |
preview = text[:1500] + ("..." if len(text) > 1500 else "")
|
| 383 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 384 |
|
| 385 |
|
| 386 |
with gr.Blocks(css=CSS, title="AI Text Detector", theme=gr.themes.Base()) as demo:
|
|
@@ -432,6 +449,12 @@ with gr.Blocks(css=CSS, title="AI Text Detector", theme=gr.themes.Base()) as dem
|
|
| 432 |
|
| 433 |
with gr.Group(elem_classes="result-card"):
|
| 434 |
url_output = gr.Label(num_top_classes=2, label="Result")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 435 |
|
| 436 |
with gr.Group(elem_classes="input-card"):
|
| 437 |
url_preview = gr.Textbox(
|
|
@@ -441,7 +464,16 @@ with gr.Blocks(css=CSS, title="AI Text Detector", theme=gr.themes.Base()) as dem
|
|
| 441 |
elem_classes="preview-box",
|
| 442 |
)
|
| 443 |
|
| 444 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 445 |
|
| 446 |
gr.HTML('<div class="examples-heading">Try an example</div>')
|
| 447 |
gr.Examples(
|
|
@@ -453,6 +485,9 @@ with gr.Blocks(css=CSS, title="AI Text Detector", theme=gr.themes.Base()) as dem
|
|
| 453 |
label="",
|
| 454 |
)
|
| 455 |
|
|
|
|
|
|
|
|
|
|
| 456 |
gr.HTML("""
|
| 457 |
<div class="info-strip">
|
| 458 |
<p>
|
|
|
|
| 1 |
"""HuggingFace Space for AI text detection using adaptive-classifier."""
|
| 2 |
|
| 3 |
import re
|
| 4 |
+
import urllib.parse
|
| 5 |
import urllib.request
|
| 6 |
from html.parser import HTMLParser
|
| 7 |
|
|
|
|
| 366 |
return {label: round(score, 4) for label, score in predictions}
|
| 367 |
|
| 368 |
|
| 369 |
+
SPACE_URL = "https://adaptive-classifier-ai-detector.hf.space"
|
| 370 |
+
|
| 371 |
+
|
| 372 |
+
def detect_url(url: str) -> tuple[dict, str, str]:
|
| 373 |
"""Fetch a URL and classify its text content."""
|
| 374 |
if not url or not url.strip():
|
| 375 |
+
return _error_label("Please enter a URL"), "", ""
|
| 376 |
try:
|
| 377 |
text = fetch_url(url)
|
| 378 |
except Exception as e:
|
| 379 |
+
return _error_label(f"Could not fetch URL: {e}"), "", ""
|
| 380 |
+
# Detect JS-only pages that return no usable content
|
| 381 |
+
js_hints = ["javascript is not available", "enable javascript", "javascript is disabled",
|
| 382 |
+
"please enable js", "requires javascript", "noscript"]
|
| 383 |
+
text_lower = text.lower()
|
| 384 |
+
if any(h in text_lower for h in js_hints) or len(text.split()) < 10:
|
| 385 |
+
if any(h in text_lower for h in js_hints):
|
| 386 |
+
return _error_label("This site requires JavaScript to load content (e.g. Twitter/X, SPAs). Try a different URL or paste the text directly."), "", ""
|
| 387 |
+
return _error_label("Not enough readable text found at that URL"), text[:500], ""
|
| 388 |
words = text.split()
|
| 389 |
if len(words) > 2000:
|
| 390 |
text = " ".join(words[:2000])
|
| 391 |
result = detect_text(text)
|
| 392 |
preview = text[:1500] + ("..." if len(text) > 1500 else "")
|
| 393 |
+
share_link = f"{SPACE_URL}/?url={urllib.parse.quote(url.strip(), safe='')}"
|
| 394 |
+
return result, preview, share_link
|
| 395 |
+
|
| 396 |
+
|
| 397 |
+
def handle_url_param(request: gr.Request):
|
| 398 |
+
"""Auto-fill URL from ?url= query parameter."""
|
| 399 |
+
url = request.query_params.get("url", "")
|
| 400 |
+
return url if url else ""
|
| 401 |
|
| 402 |
|
| 403 |
with gr.Blocks(css=CSS, title="AI Text Detector", theme=gr.themes.Base()) as demo:
|
|
|
|
| 449 |
|
| 450 |
with gr.Group(elem_classes="result-card"):
|
| 451 |
url_output = gr.Label(num_top_classes=2, label="Result")
|
| 452 |
+
share_link = gr.Textbox(
|
| 453 |
+
label="Share this result",
|
| 454 |
+
interactive=False,
|
| 455 |
+
visible=False,
|
| 456 |
+
elem_classes="preview-box",
|
| 457 |
+
)
|
| 458 |
|
| 459 |
with gr.Group(elem_classes="input-card"):
|
| 460 |
url_preview = gr.Textbox(
|
|
|
|
| 464 |
elem_classes="preview-box",
|
| 465 |
)
|
| 466 |
|
| 467 |
+
def run_url_detection(url):
|
| 468 |
+
result, preview, link = detect_url(url)
|
| 469 |
+
return result, gr.update(value=link, visible=bool(link)), preview
|
| 470 |
+
|
| 471 |
+
url_btn.click(
|
| 472 |
+
fn=run_url_detection,
|
| 473 |
+
inputs=url_input,
|
| 474 |
+
outputs=[url_output, share_link, url_preview],
|
| 475 |
+
api_name="detect_url",
|
| 476 |
+
)
|
| 477 |
|
| 478 |
gr.HTML('<div class="examples-heading">Try an example</div>')
|
| 479 |
gr.Examples(
|
|
|
|
| 485 |
label="",
|
| 486 |
)
|
| 487 |
|
| 488 |
+
# Auto-fill URL from ?url= query parameter on page load
|
| 489 |
+
demo.load(fn=handle_url_param, inputs=None, outputs=url_input)
|
| 490 |
+
|
| 491 |
gr.HTML("""
|
| 492 |
<div class="info-strip">
|
| 493 |
<p>
|