New / app.py
Pubgbc9799's picture
Update app.py
e180ad7 verified
import asyncio
import os
import re
import fitz # PyMuPDF
from flask import Flask, request, render_template_string, send_file
from playwright.async_api import async_playwright
app = Flask(__name__)
# --- UI Design ---
HTML_PAGE = """
<!DOCTYPE html>
<html>
<head>
<title>JNVU Admit Card Downloader</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body { font-family: 'Segoe UI', Arial, sans-serif; background: #f0f2f5; display: flex; justify-content: center; padding-top: 50px; }
.card { background: white; padding: 30px; border-radius: 15px; box-shadow: 0 10px 25px rgba(0,0,0,0.1); width: 100%; max-width: 450px; text-align: center; }
h2 { color: #1a73e8; margin-bottom: 20px; }
input { width: 90%; padding: 12px; margin: 10px 0; border: 2px solid #dfe1e5; border-radius: 8px; font-size: 16px; outline: none; }
input:focus { border-color: #1a73e8; }
.btn-fetch { background: #1a73e8; color: white; border: none; padding: 12px 25px; border-radius: 8px; cursor: pointer; font-size: 16px; width: 95%; font-weight: bold; }
.btn-fetch:hover { background: #1557b0; }
.result-box { margin-top: 25px; padding: 20px; background: #f8f9fa; border-radius: 10px; text-align: left; border-left: 5px solid #34a853; }
.btn-download { display: block; text-align: center; background: #34a853; color: white; padding: 12px; text-decoration: none; border-radius: 8px; margin-top: 15px; font-weight: bold; }
.error { color: #d93025; background: #fce8e6; padding: 10px; border-radius: 5px; margin-top: 10px; }
.loading { color: #5f6368; font-style: italic; margin-top: 10px; }
</style>
</head>
<body>
<div class="card">
<h2>JNVU Admit Card Finder</h2>
<form method="POST">
<input type="text" name="form_number" placeholder="Enter Form Number (e.g. 128xxx)" required>
<button type="submit" class="btn-fetch">Fetch Admit Card</button>
</form>
{% if error %}<div class="error">{{ error }}</div>{% endif %}
{% if data %}
<div class="result-box">
<p><strong>👤 Name:</strong> {{ data.name }}</p>
<p><strong>🔢 Roll No:</strong> {{ data.roll }}</p>
<p><strong>🏫 Center:</strong> {{ data.center }}</p>
<a href="/download/{{ filename }}" class="btn-download">📥 Download PDF Now</a>
</div>
{% endif %}
</div>
</body>
</html>
"""
# --- PDF Data Extraction ---
def extract_student_info(pdf_path):
info = {"name": "Not Found", "roll": "Not Found", "center": "Not Found"}
try:
doc = fitz.open(pdf_path)
text = "".join([page.get_text() for page in doc])
name_m = re.search(r"NAME OF CANDIDATE\s*:\s*(.*)", text)
roll_m = re.search(r"Roll no is\s+([\w\d]+)", text)
cent_m = re.search(r"Exam Centre is\s*(.*?)(?=Print Date|To,|The Centre|NAME OF EXAMINATION)", text, re.DOTALL)
if name_m: info["name"] = name_m.group(1).split('\n')[0].strip()
if roll_m: info["roll"] = roll_m.group(1).strip()
if cent_m: info["center"] = " ".join(cent_m.group(1).split())
doc.close()
except Exception as e: print(f"Error: {e}")
return info
# --- Playwright Logic ---
async def download_jnvu_pdf(form_number):
pdf_path = f"admit_card_{form_number}.pdf"
async with async_playwright() as p:
# Docker के लिए No-Sandbox बहुत जरूरी है
browser = await p.chromium.launch(headless=True, args=["--no-sandbox", "--disable-dev-shm-usage"])
context = await browser.new_context(accept_downloads=True)
page = await context.new_page()
try:
url = "https://erp.jnvuiums.in/(S(biolzjtwlrcfmzwwzgs5uj5n))/Exam/Pre_Exam/Exam_ForALL_AdmitCard.aspx#"
await page.goto(url, wait_until="load", timeout=40000)
await page.fill("#txtchallanNo", str(form_number))
async with page.expect_download(timeout=20000) as download_info:
await page.click("#btnGetResult")
download = await download_info.value
await download.save_as(pdf_path)
return pdf_path
except Exception as e:
print(f"Download Error: {e}")
return None
finally:
await browser.close()
# --- Routes ---
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
form_number = request.form.get('form_number')
if not form_number.isdigit():
return render_template_string(HTML_PAGE, error="कृपया सही फॉर्म नंबर डालें।")
file_path = asyncio.run(download_jnvu_pdf(form_number))
if file_path and os.path.exists(file_path):
data = extract_student_info(file_path)
return render_template_string(HTML_PAGE, data=data, filename=file_path)
else:
return render_template_string(HTML_PAGE, error="एडमिट कार्ड नहीं मिला या JNVU सर्वर धीमा है।")
return render_template_string(HTML_PAGE)
@app.route('/download/<filename>')
def download_file(filename):
# सुरक्षा के लिए चेक करें कि फाइल मौजूद है
if os.path.exists(filename):
return send_file(filename, as_attachment=True)
return "File missing", 404
if __name__ == "__main__":
# Hugging Face PORT 7860 मांगता है
port = int(os.environ.get("PORT", 7860))
app.run(host='0.0.0.0', port=port)