fallingbody/local-ai
0
1from flask import Flask, request, jsonify2from flask_cors import CORS3import os4import tempfile5import shutil6from pathlib import Path7from uuid import uuid48 9import pymupdf as fitz # PDF (using pymupdf instead of deprecated fitz)10from deepface import DeepFace11 12app = Flask(__name__)13CORS(app)14 15UPLOADS_DIR = Path("uploads")16UPLOADS_DIR.mkdir(exist_ok=True)17 18session_store = {}19resume_store = {}20 21# ========================22# SESSION23# ========================24def create_session():25 return {26 "reference_image": None,27 "verified_frames": 0,28 "total_frames": 0,29 "terminated": False30 }31 32def get_session(session_id):33 if session_id not in session_store:34 session_store[session_id] = create_session()35 return session_store[session_id]36 37# ========================38# EXTRACT IMAGE FROM PDF39# ========================40def extract_image_from_pdf(file_path, resume_id):41 doc = fitz.open(file_path)42 43 for page_index in range(len(doc)):44 page = doc[page_index]45 images = page.get_images(full=True)46 47 for img in images:48 xref = img[0]49 base = doc.extract_image(xref)50 image_bytes = base["image"]51 52 img_path = UPLOADS_DIR / f"{resume_id}.jpg"53 with open(img_path, "wb") as f:54 f.write(image_bytes)55 56 return str(img_path)57 58 return None59 60# ========================61# UPLOAD RESUME62# ========================63@app.route("/api/resumes/upload", methods=["POST"])64def upload_resume():65 file = request.files.get("file")66 name = request.form.get("name")67 email = request.form.get("email")68 69 if not file:70 return jsonify({"error": "No file"}), 40071 72 resume_id = str(uuid4())73 file_path = UPLOADS_DIR / f"{resume_id}.pdf"74 file.save(file_path)75 76 # Extract image77 image_path = extract_image_from_pdf(file_path, resume_id)78 79 if not image_path:80 return jsonify({81 "error": "Resume must contain a clear photo"82 }), 40083 84 resume_store[resume_id] = {85 "image_path": image_path86 }87 88 return jsonify({89 "message": "Resume uploaded",90 "resume_id": resume_id91 })92 93# ========================94# START SESSION95# ========================96@app.route("/start", methods=["POST"])97def start():98 data = request.json99 session_id = data.get("session_id")100 resume_id = data.get("resume_id")101 102 if resume_id not in resume_store:103 return jsonify({"error": "Invalid resume"}), 400104 105 session = create_session()106 session["reference_image"] = resume_store[resume_id]["image_path"]107 108 session_store[session_id] = session109 110 return jsonify({"message": "Session started"})111 112# ========================113# VERIFY FACE114# ========================115@app.route("/verify-face", methods=["POST"])116def verify_face():117 session_id = request.form.get("session_id")118 image = request.files.get("image")119 120 session = get_session(session_id)121 122 if session.get("terminated"):123 return jsonify({124 "terminated": True,125 "reason": "Already terminated"126 }), 403127 128 if not image:129 return jsonify({"error": "No image"}), 400130 131 with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp:132 path = temp.name133 image.save(path)134 135 try:136 result = DeepFace.verify(137 img1_path=session["reference_image"],138 img2_path=path,139 enforce_detection=False140 )141 142 verified = result["verified"]143 distance = result["distance"]144 145 session["total_frames"] += 1146 147 if verified:148 session["verified_frames"] += 1149 150 # 🚨 CHEATING DETECTION151 if not verified:152 session["terminated"] = True153 154 return jsonify({155 "terminated": True,156 "reason": "CHEATING DETECTED",157 "verified": False158 }), 403159 160 return jsonify({161 "verified": True,162 "distance": distance163 })164 165 except Exception as e:166 return jsonify({"error": str(e)}), 500167 168 finally:169 os.remove(path)170 171# ========================172# END SESSION173# ========================174@app.route("/end", methods=["POST"])175def end():176 data = request.json177 session_id = data.get("session_id")178 179 session = get_session(session_id)180 181 total_frames = session.get("total_frames", 0)182 verified_frames = session.get("verified_frames", 0)183 184 verification_rate = (185 (verified_frames / total_frames) * 100186 if total_frames else 0187 )188 189 return jsonify({190 "verification_rate": round(verification_rate, 2),191 "status": "verified" if verification_rate > 60 else "suspicious",192 "terminated": session.get("terminated", False),193 "total_frames": total_frames,194 "verified_frames": verified_frames,195 })196 197# ========================198# RUN199# ========================200if __name__ == "__main__":201 app.run(port=5000, debug=True)