from flask import Flask, render_template, request, redirect, url_for, send_file import os from flask import session from resume_parser import extract_resume_text from matching_engine import calculate_similarity, get_top_job_matches from scam_model import predict_scam from skill_analyzer import analyze_skill_gap from feedback_engine import generate_feedback from skill_extractor import extract_skills from warning_engine import detect_warnings app = Flask(__name__) app.config["UPLOAD_FOLDER"] = "uploads" # ---------------- HOME ---------------- @app.route("/") def index(): return render_template("index.html") # ---------------- PROCESS RESUME ---------------- @app.route("/process", methods=["POST"]) def process(): resume_text = request.form.get("resume_text", "").strip() uploaded_file = request.files.get("resume_file") final_resume = "" if uploaded_file and uploaded_file.filename != "": filepath = os.path.join(app.config["UPLOAD_FOLDER"], uploaded_file.filename) uploaded_file.save(filepath) final_resume = extract_resume_text(filepath) elif resume_text: final_resume = resume_text else: return redirect(url_for("index")) return render_template("upload_jd.html", resume=final_resume) # ---------------- ANALYZE ---------------- @app.route("/analyze", methods=["POST"]) def analyze(): resume = request.form.get("resume", "").strip() jd = request.form.get("jd_text", "").strip() if not resume or not jd: return "Missing resume or job description", 400 match_score = calculate_similarity(resume, jd) jobs = get_top_job_matches(resume) skills = extract_skills(resume) skill_data = analyze_skill_gap(resume, jd) if not isinstance(skill_data, dict): skill_data = {"matched": [], "missing": [], "match_ratio": 0} feedback = generate_feedback(resume, skill_data) return render_template( "result.html", match_score=match_score, jobs=jobs, skills=skills, resume=resume, jd=jd, skill_data=skill_data, feedback=feedback ) # ---------------- SCAM CHECKER ---------------- @app.route("/scam-checker") def scam_checker(): return render_template("scam_checker.html") @app.route("/analyze-scam", methods=["POST"]) def analyze_scam(): email = request.form.get("email", "") title = request.form.get("title", "") description = request.form.get("description", "") score, label = predict_scam(email, title, description) warnings = detect_warnings(email, title, description) return render_template( "scam_result.html", result=label, score=score, warnings=warnings ) # ---------------- DOWNLOAD REPORT ---------------- @app.route("/download-report", methods=["POST"]) def download_report(): from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer from reportlab.lib.styles import getSampleStyleSheet from flask import send_file, request pdf_path = "report.pdf" doc = SimpleDocTemplate(pdf_path) styles = getSampleStyleSheet() elements = [] resume = request.form.get("resume", "") jd = request.form.get("jd_text", "") match_score = request.form.get("match_score", 0) elements.append(Paragraph("JobShield AI Report", styles["Title"])) elements.append(Spacer(1, 20)) elements.append(Paragraph(f"Match Score: {match_score}%", styles["BodyText"])) elements.append(Spacer(1, 10)) elements.append(Paragraph("Resume Preview:", styles["Heading2"])) elements.append(Paragraph(resume[:1000], styles["BodyText"])) elements.append(Spacer(1, 10)) elements.append(Paragraph("Job Description Preview:", styles["Heading2"])) elements.append(Paragraph(jd[:1000], styles["BodyText"])) doc.build(elements) return send_file(pdf_path, as_attachment=True) # ---------------- RUN ---------------- if __name__ == "__main__": os.makedirs(app.config["UPLOAD_FOLDER"], exist_ok=True) app.run(host="0.0.0.0", port=7860) # from flask import Flask, render_template, request, redirect, url_for, send_file, session # import os # from resume_parser import extract_resume_text # from matching_engine import calculate_similarity, get_top_job_matches # from scam_model import predict_scam # from skill_analyzer import analyze_skill_gap # from feedback_engine import generate_feedback # from skill_extractor import extract_skills # from warning_engine import detect_warnings # app = Flask(__name__) # app.secret_key = "secret_key_change_this" # app.config["UPLOAD_FOLDER"] = "uploads" # # ---------------- HOME ---------------- # @app.route("/") # def index(): # return render_template("index.html") # # ---------------- PROCESS RESUME ---------------- # @app.route('/process', methods=['POST']) # def process(): # resume_text = request.form.get("resume_text", "").strip() # uploaded_file = request.files.get("resume_file") # final_resume = "" # if uploaded_file and uploaded_file.filename != "": # filepath = os.path.join(app.config["UPLOAD_FOLDER"], uploaded_file.filename) # uploaded_file.save(filepath) # final_resume = extract_resume_text(filepath) # elif resume_text: # final_resume = resume_text # else: # return redirect(url_for("index")) # # store in session (IMPORTANT FIX) # session["resume"] = final_resume # return render_template("upload_jd.html", resume=final_resume) # # ---------------- ANALYZE ---------------- # @app.route('/analyze', methods=['POST']) # def analyze(): # resume = request.form.get("resume", "").strip() # jd = request.form.get("jd_text", "").strip() # print("RESUME LENGTH:", len(resume)) # print("JD LENGTH:", len(jd)) # if not resume or not jd: # return "Missing resume or job description", 400 # match_score = calculate_similarity(resume, jd) # jobs = get_top_job_matches(resume) # skills = extract_skills(resume) # skill_data = analyze_skill_gap(resume, jd) # if not isinstance(skill_data, dict): # skill_data = {"matched": [], "missing": [], "match_ratio": 0} # feedback = generate_feedback(resume, skill_data) # # store for PDF # session["match_score"] = match_score # session["resume"] = resume # session["jd"] = jd # session["skill_data"] = skill_data # session["feedback"] = feedback # return render_template( # "result.html", # match_score=match_score, # jobs=jobs, # skills=skills, # resume=resume[:300], # jd=jd[:300], # skill_data=skill_data, # feedback=feedback # ) # # ---------------- SCAM CHECKER ---------------- # @app.route('/scam-checker') # def scam_checker(): # return render_template("scam_checker.html") # @app.route('/analyze-scam', methods=['POST']) # def analyze_scam(): # email = request.form.get("email", "") # title = request.form.get("title", "") # description = request.form.get("description", "") # score, label = predict_scam(email, title, description) # warnings = detect_warnings(email, title, description) # if label == "Scam": # precautions = [ # "Do not pay money", # "Do not share bank details", # "Verify company website", # "Check LinkedIn presence", # "Be careful of urgency traps" # ] # elif label == "Medium Risk": # precautions = [ # "Verify recruiter email", # "Check reviews", # "Avoid suspicious links" # ] # else: # precautions = ["Still verify company authenticity"] # return render_template( # "scam_result.html", # result=label, # score=score, # precautions=precautions, # warnings=warnings # ) # # ---------------- DOWNLOAD PDF REPORT ---------------- # @app.route('/download-report') # def download_report(): # from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer # from reportlab.lib.styles import getSampleStyleSheet # pdf_path = os.path.join("/tmp", "report.pdf") # doc = SimpleDocTemplate(pdf_path) # styles = getSampleStyleSheet() # elements = [] # match_score = session.get("match_score", 0) # resume = session.get("resume", "") # jd = session.get("jd", "") # skill_data = session.get("skill_data", {"matched": [], "missing": []}) # feedback = session.get("feedback", []) # elements.append(Paragraph("JobShield AI Report", styles['Title'])) # elements.append(Spacer(1, 20)) # elements.append(Paragraph(f"Match Score: {match_score}%", styles['BodyText'])) # elements.append(Spacer(1, 10)) # elements.append(Paragraph("Matched Skills:", styles['Heading2'])) # for skill in skill_data.get("matched", []): # elements.append(Paragraph(f"• {skill}", styles['BodyText'])) # elements.append(Spacer(1, 10)) # elements.append(Paragraph("Missing Skills:", styles['Heading2'])) # for skill in skill_data.get("missing", []): # elements.append(Paragraph(f"• {skill}", styles['BodyText'])) # elements.append(Spacer(1, 10)) # elements.append(Paragraph("Resume Feedback:", styles['Heading2'])) # for f in feedback: # elements.append(Paragraph(f"• {f}", styles['BodyText'])) # elements.append(Spacer(1, 10)) # elements.append(Paragraph("Resume Preview:", styles['Heading2'])) # elements.append(Paragraph(resume[:1000], styles['BodyText'])) # elements.append(Spacer(1, 10)) # elements.append(Paragraph("Job Description Preview:", styles['Heading2'])) # elements.append(Paragraph(jd[:1000], styles['BodyText'])) # doc.build(elements) # return send_file(pdf_path, as_attachment=True) # # ---------------- RUN ---------------- # if __name__ == "__main__": # os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) # print("Starting JobShield AI...") # app.run(host="0.0.0.0", port=7860) # from flask import Flask, render_template, request, redirect, url_for, send_file # import os # from resume_parser import extract_resume_text # from matching_engine import calculate_similarity, get_top_job_matches # from scam_model import predict_scam # from skill_analyzer import analyze_skill_gap # from feedback_engine import generate_feedback # from skill_extractor import extract_skills # from warning_engine import detect_warnings # app = Flask(__name__) # app.config["UPLOAD_FOLDER"] = "uploads" # # ---------------- HOME ---------------- # @app.route("/") # def index(): # return render_template("index.html") # # ---------------- PROCESS RESUME ---------------- # @app.route('/process', methods=['POST']) # def process(): # resume_text = request.form.get("resume_text", "").strip() # uploaded_file = request.files.get("resume_file") # final_resume = "" # # FILE INPUT # if uploaded_file and uploaded_file.filename != "": # filepath = os.path.join(app.config["UPLOAD_FOLDER"], uploaded_file.filename) # uploaded_file.save(filepath) # final_resume = extract_resume_text(filepath) # # TEXT INPUT # elif resume_text: # final_resume = resume_text # else: # return redirect(url_for("index")) # # PASS DIRECTLY TO JD PAGE (NO SESSION) # return render_template("upload_jd.html", resume=final_resume) # # ---------------- ANALYZE ---------------- # @app.route('/analyze', methods=['POST']) # def analyze(): # resume = request.form.get("resume", "").strip() # jd = request.form.get("jd_text", "").strip() # print("RESUME LENGTH:", len(resume)) # print("JD LENGTH:", len(jd)) # if not resume or not jd: # return "Missing resume or job description", 400 # match_score = calculate_similarity(resume, jd) # jobs = get_top_job_matches(resume) # skills = extract_skills(resume) # skill_data = analyze_skill_gap(resume, jd) # if not isinstance(skill_data, dict): # skill_data = {"matched": [], "missing": [], "match_ratio": 0} # feedback = generate_feedback(resume, skill_data) # return render_template( # "result.html", # match_score=match_score, # jobs=jobs, # skills=skills, # resume=resume[:300], # jd=jd[:300], # skill_data=skill_data, # feedback=feedback # ) # # ---------------- SCAM CHECKER ---------------- # @app.route('/scam-checker') # def scam_checker(): # return render_template("scam_checker.html") # @app.route('/analyze-scam', methods=['POST']) # def analyze_scam(): # email = request.form.get("email", "") # title = request.form.get("title", "") # description = request.form.get("description", "") # score, label = predict_scam(email, title, description) # warnings = detect_warnings(email, title, description) # if label == "Scam": # precautions = [ # "Do not pay money", # "Do not share bank details", # "Verify company website", # "Check LinkedIn presence", # "Be careful of urgency traps" # ] # elif label == "Medium Risk": # precautions = [ # "Verify recruiter email", # "Check reviews", # "Avoid suspicious links" # ] # else: # precautions = ["Still verify company authenticity"] # return render_template( # "scam_result.html", # result=label, # score=score, # precautions=precautions, # warnings=warnings # ) # # ---------------- DOWNLOAD PDF REPORT ---------------- # @app.route('/download-report') # def download_report(): # from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer # from reportlab.lib.styles import getSampleStyleSheet # from flask import send_file # pdf_path = "report.pdf" # doc = SimpleDocTemplate(pdf_path) # styles = getSampleStyleSheet() # elements = [] # # DATA # match_score = session.get("match_score", 0) # resume = session.get("resume", "") #resume = request.form.get("resume", "") # jd = session.get("jd", "") # skill_data = session.get("skill_data", { # "matched": [], # "missing": [] # }) # feedback = session.get("feedback", []) # # TITLE # elements.append(Paragraph("JobShield AI Report", styles['Title'])) # elements.append(Spacer(1, 20)) # # SCORE # elements.append(Paragraph(f"Match Score: {match_score}%", styles['BodyText'])) # elements.append(Spacer(1, 10)) # # MATCHED # elements.append(Paragraph("Matched Skills:", styles['Heading2'])) # for skill in skill_data["matched"]: # elements.append(Paragraph(f"• {skill}", styles['BodyText'])) # elements.append(Spacer(1, 10)) # # MISSING # elements.append(Paragraph("Missing Skills:", styles['Heading2'])) # for skill in skill_data["missing"]: # elements.append(Paragraph(f"• {skill}", styles['BodyText'])) # elements.append(Spacer(1, 10)) # # FEEDBACK # elements.append(Paragraph("Resume Feedback:", styles['Heading2'])) # for f in feedback: # elements.append(Paragraph(f"• {f}", styles['BodyText'])) # elements.append(Spacer(1, 10)) # # RESUME # elements.append(Paragraph("Resume Preview:", styles['Heading2'])) # elements.append(Paragraph(resume[:1000], styles['BodyText'])) # elements.append(Spacer(1, 10)) # # JD # elements.append(Paragraph("Job Description Preview:", styles['Heading2'])) # elements.append(Paragraph(jd[:1000], styles['BodyText'])) # # BUILD PDF # doc.build(elements) # return send_file(pdf_path, as_attachment=True) # # ---------------- RUN ---------------- # if __name__ == "__main__": # os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) # print("Starting JobShield AI...") # app.run(host="0.0.0.0", port=7860) # from flask import Flask, render_template, request, redirect, url_for, session # import os # from resume_parser import extract_resume_text # from matching_engine import calculate_similarity, get_top_job_matches # from scam_model import predict_scam # from skill_analyzer import analyze_skill_gap # from feedback_engine import generate_feedback # from skill_extractor import extract_skills # from warning_engine import detect_warnings # app = Flask(__name__) # app.secret_key = "secret_key_change_this" # app.config["UPLOAD_FOLDER"] = "uploads" # # ---------------- HOME ---------------- # @app.route("/") # def index(): # session.clear() # return render_template("index.html") # # ---------------- PROCESS RESUME ---------------- # @app.route('/process', methods=['POST']) # def process(): # resume_text = request.form.get("resume_text", "").strip() # uploaded_file = request.files.get("resume_file") # final_resume = "" # # FILE # if uploaded_file and uploaded_file.filename != "": # filepath = os.path.join(app.config["UPLOAD_FOLDER"], uploaded_file.filename) # uploaded_file.save(filepath) # final_resume = extract_resume_text(filepath) # session["uploaded_file"] = uploaded_file.filename # # TEXT # elif resume_text: # final_resume = resume_text # session.pop("uploaded_file", None) # else: # print("Resume text:", resume_text) # print("JD text:", jd_text) # print("Analyze route reached") # return redirect(url_for("index")) # # STORE RESUME # app.config["FULL_RESUME"] = final_resume # return render_template("upload_jd.html", resume=final_resume) # # ---------------- JD PAGE ---------------- # @app.route('/upload_jd') # def upload_jd(): # return render_template("upload_jd.html") # # ---------------- ANALYZE ---------------- # @app.route('/analyze', methods=['POST']) # def analyze(): # print("ANALYZE ROUTE HIT") # print("FORM DATA:", request.form) # print("SESSION:", session) # resume_text = session.get("resume") # print("RESUME:", resume_text) # jd_text = request.form.get("job_description") # print("JD:", jd_text) # jd = request.form.get("jd_text", "") # resume = request.form.get("resume", "") # if not jd.strip() or not resume.strip(): # return "Missing resume or job description", 400 # match_score = calculate_similarity(resume, jd) # jobs = get_top_job_matches(resume) # skills = extract_skills(resume) # # SAFE CALL (ONLY IMPORTED FUNCTION) # skill_data = analyze_skill_gap(resume, jd) # # SAFE fallback (prevents Jinja crash) # if not isinstance(skill_data, dict): # skill_data = {"matched": [], "missing": [], "match_ratio": 0} # feedback = generate_feedback(resume, skill_data) # session["match_score"] = match_score # session["resume"] = resume # session["jd"] = jd # session["skill_data"] = skill_data # session["feedback"] = feedback # return render_template( # "result.html", # match_score=match_score, # jobs=jobs, # skills=skills, # resume=resume[:300], # jd=jd[:300], # skill_data=skill_data, # feedback=feedback # ) # # ---------------- RESULT PAGE ---------------- # @app.route("/result") # def result(): # return render_template( # "result.html", # match_score=0, # jobs=[], # skills=[], # skill_data={"matched": [], "missing": []}, # resume="", # jd="", # feedback=[] # ) # # ---------------- DOWNLOAD PDF REPORT ---------------- # @app.route('/download-report') # def download_report(): # from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer # from reportlab.lib.styles import getSampleStyleSheet # from flask import send_file # pdf_path = "report.pdf" # doc = SimpleDocTemplate(pdf_path) # styles = getSampleStyleSheet() # elements = [] # # DATA # match_score = session.get("match_score", 0) # resume = session.get("resume", "") #resume = request.form.get("resume", "") # jd = session.get("jd", "") # skill_data = session.get("skill_data", { # "matched": [], # "missing": [] # }) # feedback = session.get("feedback", []) # # TITLE # elements.append(Paragraph("JobShield AI Report", styles['Title'])) # elements.append(Spacer(1, 20)) # # SCORE # elements.append(Paragraph(f"Match Score: {match_score}%", styles['BodyText'])) # elements.append(Spacer(1, 10)) # # MATCHED # elements.append(Paragraph("Matched Skills:", styles['Heading2'])) # for skill in skill_data["matched"]: # elements.append(Paragraph(f"• {skill}", styles['BodyText'])) # elements.append(Spacer(1, 10)) # # MISSING # elements.append(Paragraph("Missing Skills:", styles['Heading2'])) # for skill in skill_data["missing"]: # elements.append(Paragraph(f"• {skill}", styles['BodyText'])) # elements.append(Spacer(1, 10)) # # FEEDBACK # elements.append(Paragraph("Resume Feedback:", styles['Heading2'])) # for f in feedback: # elements.append(Paragraph(f"• {f}", styles['BodyText'])) # elements.append(Spacer(1, 10)) # # RESUME # elements.append(Paragraph("Resume Preview:", styles['Heading2'])) # elements.append(Paragraph(resume[:1000], styles['BodyText'])) # elements.append(Spacer(1, 10)) # # JD # elements.append(Paragraph("Job Description Preview:", styles['Heading2'])) # elements.append(Paragraph(jd[:1000], styles['BodyText'])) # # BUILD PDF # doc.build(elements) # return send_file(pdf_path, as_attachment=True) # # ---------------- SCAM CHECKER ---------------- # @app.route('/scam-checker') # def scam_checker(): # return render_template("scam_checker.html") # @app.route('/analyze-scam', methods=['POST']) # def analyze_scam(): # email = request.form.get("email", "") # title = request.form.get("title", "") # description = request.form.get("description", "") # score, label = predict_scam(email, title, description) # warnings = detect_warnings(email, title, description) # if label == "Scam": # precautions = [ # "Do not pay money", # "Do not share bank details", # "Verify company website", # "Check LinkedIn presence", # "Be careful of urgency traps" # ] # elif label == "Medium Risk": # precautions = [ # "Verify recruiter email", # "Check reviews", # "Avoid suspicious links" # ] # else: # precautions = [ # "Still verify company authenticity" # ] # return render_template( # "scam_result.html", # result=label, # score=score, # precautions=precautions, # warnings=warnings # ) # # ---------------- RUN ---------------- # if __name__ == "__main__": # os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) # print("Starting JobShield AI...") # app.run(host="0.0.0.0", port=7860)