number-api / app.py
Noobster1's picture
Rename main.py to app.py
45eff34 verified
Raw
History Blame Contribute Delete
4.12 kB
from fastapi import FastAPI, Query
import duckdb
from contextlib import asynccontextmanager
import re
app = FastAPI()
con = None
@asynccontextmanager
async def lifespan(app: FastAPI):
global con
print("🟢 Starting...")
con = duckdb.connect()
con.execute("INSTALL httpfs; LOAD httpfs;")
PARQUET_URL = "https://huggingface.co/datasets/tfqdeadlo/Inddatainonefile/resolve/main/users_data.parquet"
try:
print("🟡 Loading parquet...")
con.execute(f"CREATE OR REPLACE VIEW users_view AS SELECT * FROM read_parquet('{PARQUET_URL}')")
count = con.execute("SELECT COUNT(*) FROM users_view").fetchone()[0]
print(f"✅ Loaded! {count:,} records")
except Exception as e:
print(f"❌ Error: {e}")
con.execute("""
CREATE OR REPLACE VIEW users_view AS
SELECT * FROM (VALUES
('9999999891', 'Krishan Bidhuri', 'Dharamveer', 'Delhi', '9999599891', 'AIRTEL DELHI', '417479131232', 'krishan@email.com'),
('9999999751', 'Manoj Sharawat', 'Rajender', 'Delhi', NULL, 'AIRTEL DELHI', '423900570509', NULL),
) AS t(mobile, name, fname, address, alt, circle, id, email)
""")
yield
con.close()
app.router.lifespan_context = lifespan
# Helper function to format result
def format_result(result):
columns = ['mobile', 'name', 'fname', 'address', 'alt', 'circle', 'id', 'email']
return {
"status": "success",
"data": dict(zip(columns, result))
}
# 1️⃣ API: Mobile Number se data fetch karein
@app.get("/search/mobile")
async def search_by_mobile(mobile: str = Query(..., description="10-digit mobile number")):
mobile_clean = str(mobile).strip()
if not re.match(r'^\d{10}$', mobile_clean):
return {"status": "error", "message": "Mobile number must be 10 digits"}
try:
result = con.execute("SELECT * FROM users_view WHERE mobile = ? LIMIT 1", [mobile_clean]).fetchone()
if not result:
return {"status": "not_found", "message": f"Mobile {mobile_clean} not found"}
return format_result(result)
except Exception as e:
return {"status": "error", "message": str(e)}
# 2️⃣ API: Gmail / Email se data fetch karein
@app.get("/search/email")
async def search_by_email(email: str = Query(..., description="Email address")):
email_clean = str(email).strip().lower()
try:
# Email validation regex
if not re.match(r"^[\w\.-]+@[\w\.-]+\.\w+$", email_clean):
return {"status": "error", "message": "Invalid email format"}
result = con.execute("SELECT * FROM users_view WHERE LOWER(email) = ? LIMIT 1", [email_clean]).fetchone()
if not result:
return {"status": "not_found", "message": f"Email {email_clean} not found"}
return format_result(result)
except Exception as e:
return {"status": "error", "message": str(e)}
# 3️⃣ API: 12-digit ID number se data fetch karein
@app.get("/search/id")
async def search_by_id(id_num: str = Query(..., description="12-digit ID number")):
id_clean = str(id_num).strip()
# 12 digits validation
if not re.match(r'^\d{12}$', id_clean):
return {"status": "error", "message": "ID must be exactly 12 digits"}
try:
result = con.execute("SELECT * FROM users_view WHERE id = ? LIMIT 1", [id_clean]).fetchone()
if not result:
return {"status": "not_found", "message": f"ID {id_clean} not found"}
return format_result(result)
except Exception as e:
return {"status": "error", "message": str(e)}
# Health / Stats Endpoints
@app.get("/stats")
async def stats():
try:
count = con.execute("SELECT COUNT(*) FROM users_view").fetchone()[0]
return {"status": "success", "total_records": count}
except:
return {"status": "error"}
@app.get("/health")
async def health():
try:
con.execute("SELECT 1").fetchone()
return {"status": "healthy", "database": "connected"}
except:
return {"status": "unhealthy"}