File size: 5,214 Bytes
d08010b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6c64f41
d08010b
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
from flask import Flask, request, jsonify, render_template, send_file
from PIL import Image
import io
import requests

from text_detector import predict_text
from image_detector import predict_image_combined
from url_handler import scrape_url
app = Flask(__name__)

# =======================
# HOME
# =======================
@app.route("/")
def home():
    return render_template("index.html")
# =======================
# TEXT
# =======================
@app.route("/predict-text", methods=["POST"])
def predict_text_api():
    data = request.get_json()
    text = data.get("text", "").strip()

    if not text or len(text) < 50:
        return jsonify({"error": "Please provide at least 50 characters."}), 400

    try:
        result = predict_text(text)
        return jsonify({
            "label":      result["final"]["label"],
            "confidence": result["final"]["confidence"],
            "warning":    result.get("warning"),
            "details":    result
        })
    except Exception as e:
        return jsonify({"error": str(e)}), 500
# =======================
# IMAGE
# =======================
@app.route("/predict-image", methods=["POST"])
def predict_image_api():
    if "image" not in request.files:
        return jsonify({"error": "No image provided."}), 400

    file = request.files["image"]
    if file.filename == "":
        return jsonify({"error": "Empty filename."}), 400

    try:
        image  = Image.open(file.stream).convert("RGB")
        result = predict_image_combined(image)
        return jsonify(result)
    except Exception as e:
        return jsonify({"error": str(e)}), 500


# =======================
# URL
# =======================
@app.route("/predict-url", methods=["POST"])
def predict_url_api():
    data = request.get_json()
    url  = data.get("url", "").strip()

    if not url:
        return jsonify({"error": "No URL provided."}), 400

    if not url.startswith("http"):
        url = "https://" + url

    # ── Scrape ────────────────────────────────────────────────
    try:
        scraped = scrape_url(url)
    except Exception as e:
        return jsonify({"error": f"Failed to scrape URL: {str(e)}"}), 400

    if not scraped.get("text"):
        return jsonify({"error": "Could not extract text from this URL."}), 400

    # ── Text analysis ─────────────────────────────────────────
    try:
        text_result = predict_text(scraped["text"])
        text_final  = text_result["final"]
        text_ai_score = (
            text_final["confidence"]
            if text_final["label"] == "AI-generated"
            else 1 - text_final["confidence"]
        )
    except Exception as e:
        text_final    = {"label": "Error", "confidence": 0.5}
        text_ai_score = 0.5

    # ── Image analysis (first 5 images) ──────────────────────
    image_results  = []
    images_checked = 0

    for img_url in scraped.get("images", [])[:5]:
        try:
            resp = requests.get(img_url, timeout=8, headers={"User-Agent": "Mozilla/5.0"})
            img  = Image.open(io.BytesIO(resp.content)).convert("RGB")
            r    = predict_image_combined(img)
            image_results.append(r)
            images_checked += 1
        except Exception:
            continue

    if image_results:
        avg_ai = sum(r["ai_score"] for r in image_results) / len(image_results)
        image_final = {
            "label":      "AI-generated" if avg_ai >= 0.5 else "Real",
            "confidence": round(float(avg_ai), 3)
        }
        img_ai_score = avg_ai
    else:
        image_final  = None
        img_ai_score = None

    # ── Combined score (60% text, 40% image) ─────────────────
    if img_ai_score is not None:
        combined_score = round(0.60 * text_ai_score + 0.40 * img_ai_score, 3)
    else:
        combined_score = round(text_ai_score, 3)

    return jsonify({
        "title":          scraped.get("title", ""),
        "text_preview":   scraped["text"][:300] + "..." if len(scraped["text"]) > 300 else scraped["text"],
        "image_url":      scraped.get("images", [None])[0],
        "image_urls":     scraped.get("images", []),
        "images_checked": images_checked,
        "text_result":    text_final,
        "image_result":   image_final,
        "combined_score": combined_score,
        "combined_label": "AI-generated" if combined_score >= 0.5 else "Human-written"
    })


# =======================
# PDF DOWNLOAD (optional)
# =======================
@app.route("/download-pdf", methods=["POST"])
def download_pdf():
    try:
        from pdf_generator import generate_pdf
        data     = request.get_json()
        filename = generate_pdf(data)
        return send_file(filename, as_attachment=True)
    except Exception as e:
        return jsonify({"error": str(e)}), 500


# =======================
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=7860, debug=False)

# .venv\Scripts\activate
# python app.py