Files changed (5) hide show
  1. Dockerfile +5 -15
  2. README.md +7 -29
  3. app.py +61 -55
  4. pinger.py +8 -22
  5. requirements.txt +2 -2
Dockerfile CHANGED
@@ -1,20 +1,10 @@
1
- FROM python:3.11-slim
2
 
3
- RUN apt-get update && \
4
- apt-get install -y --no-install-recommends ca-certificates && \
5
- rm -rf /var/lib/apt/lists/*
6
 
7
- WORKDIR /app
8
-
9
- COPY requirements.txt .
10
- RUN pip install --no-cache-dir -r requirements.txt
11
 
12
  COPY . .
13
 
14
- ENV PING_URL=http://127.0.0.1:7860/health
15
- ENV PING_INTERVAL=240
16
- ENV PYTHONUNBUFFERED=1
17
-
18
- EXPOSE 7860
19
-
20
- CMD ["sh", "-c", "python pinger.py & uvicorn app:app --host 0.0.0.0 --port 7860"]
 
1
+ FROM python:3.9
2
 
3
+ WORKDIR /code
 
 
4
 
5
+ COPY ./requirements.txt /code/requirements.txt
6
+ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
 
 
7
 
8
  COPY . .
9
 
10
+ CMD ["sh", "-c", "python pinger.py & uvicorn app:app --host 0.0.0.0 --port 7860"]
 
 
 
 
 
 
README.md CHANGED
@@ -1,31 +1,9 @@
1
  ---
2
- title: Fast Search API
3
- emoji: ⚡
4
- colorFrom: blue
5
- colorTo: purple
6
- sdk: docker
7
- app_port: 7860
8
- pinned: true
9
- license: mit
10
  ---
11
-
12
- # Fast Search API (1.78B)
13
-
14
- - ⚡ **Mobile** → sorted `mobile` column (~2-3s)
15
- - 🆔 **Aadhaar** → `id` column as aadharNumber (unsorted, slow scan)
16
-
17
- ## API
18
-
19
- ```
20
- GET /search?q=<mobile>&limit=5
21
- GET /search?mobile=<number>
22
- GET /search?aadhar=<aadhaar>
23
- GET /health
24
- GET /docs
25
- ```
26
-
27
- ## Source
28
-
29
- - DB: [tfqdeadlo/Inddatainonefile](https://huggingface.co/datasets/tfqdeadlo/Inddatainonefile)
30
- - Developer: @kzr0x
31
- - Team: TEAM DARK KNIGHT APIs
 
1
  ---
 
 
 
 
 
 
 
 
2
  ---
3
+ title: ICMR FastAPI Search
4
+ emoji: 🚀
5
+ colorFrom: yellow
6
+ colorTo: indigo
7
+ sdk: docker
8
+ pinned: false
9
+ ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.py CHANGED
@@ -1,83 +1,89 @@
1
  from fastapi import FastAPI, HTTPException, Query
2
  import duckdb
3
  from contextlib import asynccontextmanager
 
4
 
5
- # Global connection object
6
- con = duckdb.connect()
 
 
 
 
 
 
 
7
 
8
- # Lifespan use karke app start hote hi heavy initialization ek baar karenge
9
  @asynccontextmanager
10
  async def lifespan(app: FastAPI):
11
- print("DuckDB extensions load ho rahi hain aur View ban raha hai...")
 
 
 
 
 
 
 
12
  con.execute("INSTALL httpfs; LOAD httpfs;")
13
-
14
- # Parquet file ka correct URL
15
- PARQUET_URL = "https://huggingface.co/datasets/tfqdeadlo/Inddatainonefile/resolve/main/users_data.parquet"
16
-
17
- # Startup par hi Ek baar View bana kar metadata cache kar lete hain
18
- # Isse har API request par network par load nahi padega
19
- con.execute(f"CREATE OR REPLACE VIEW users_view AS SELECT * FROM read_parquet('{PARQUET_URL}')")
20
- print("View taiyar hai! API requests ke liye taiyar hai.")
21
  yield
22
  con.close()
23
 
24
- app = FastAPI(title="Super Fast Search API", lifespan=lifespan)
25
 
26
- @app.get("/")
27
- def home():
28
- return {"message": "Fast API online hai! Use /search?mobile=YOUR_NUMBER"}
29
 
30
- @app.get("/health")
31
- def health():
32
- return {"status": "ok"}
 
 
 
 
33
 
34
  @app.get("/search")
35
- async def search_mobile(
36
- mobile: str | None = Query(None),
37
- q: str | None = Query(None),
38
- num: str | None = Query(None),
39
- number: str | None = Query(None),
40
- phone: str | None = Query(None),
41
- aadhar: str | None = Query(None),
42
- aadhaar: str | None = Query(None),
43
  ):
44
- target = (q or mobile or num or number or phone or aadhar or aadhaar or "").strip()
45
- if not target:
46
- raise HTTPException(status_code=422, detail="Enter mobile number to search")
 
 
 
 
 
 
 
 
 
 
47
  try:
48
- # Mobile pehle (sorted, fast)
49
- query = """
50
- SELECT mobile, name, fname, address, alt, circle, id, email
51
- FROM users_view
52
- WHERE mobile = ?
53
  LIMIT 1
54
  """
55
- result = con.execute(query, [str(target)]).fetchall()
56
- # 12-digit mobile pe na mile to id (aadhar) pe try
57
- if not result and target.isdigit() and len(target) == 12:
58
- query2 = """
59
- SELECT mobile, name, fname, address, alt, circle, id, email
60
- FROM users_view
61
- WHERE id = ?
62
- LIMIT 1
63
- """
64
- result = con.execute(query2, [str(target)]).fetchall()
65
-
66
  if not result:
67
  return {
68
  "status": "error",
69
- "message": f"Mobile number {target} nahi mila."
 
70
  }
71
-
72
- # Data mapping
73
  columns = [desc[0] for desc in con.description]
74
- row_dict = dict(zip(columns, result[0]))
75
-
76
  return {
77
  "status": "success",
78
- "data": row_dict
 
79
  }
80
-
81
  except Exception as e:
82
- # Internal error ko secure rakhne ke liye mask kiya hai
83
- raise HTTPException(status_code=500, detail="Query timeout ya process nahi ho payi.")
 
1
  from fastapi import FastAPI, HTTPException, Query
2
  import duckdb
3
  from contextlib import asynccontextmanager
4
+ from datetime import datetime, timedelta
5
 
6
+ # === VALIDITY CHECK ===
7
+ DEPLOYMENT_DATE = datetime(2026, 6, 27) # Tune aaj deploy kiya hai
8
+ EXPIRY_DAYS = 21 # 3 weeks
9
+
10
+ def is_api_valid():
11
+ return datetime.now() < DEPLOYMENT_DATE + timedelta(days=EXPIRY_DAYS)
12
+
13
+ # Global Connection
14
+ con = None
15
 
 
16
  @asynccontextmanager
17
  async def lifespan(app: FastAPI):
18
+ global con
19
+ print("🟢 DuckDB initialize ho raha hai...")
20
+
21
+ con = duckdb.connect()
22
+ con.execute("PRAGMA memory_limit='800MB'")
23
+ con.execute("PRAGMA threads=2")
24
+ con.execute("SET enable_object_cache=true")
25
+ con.execute("SET preserve_insertion_order=false")
26
  con.execute("INSTALL httpfs; LOAD httpfs;")
27
+
28
+ URL_ICMR = "https://huggingface.co/datasets/kzropx/icmr-parquet/resolve/main/icmr.parquet"
29
+ con.execute(f"SELECT 1 FROM read_parquet('{URL_ICMR}') LIMIT 1")
30
+ print("🟢 DuckDB ready!")
 
 
 
 
31
  yield
32
  con.close()
33
 
34
+ app = FastAPI(lifespan=lifespan)
35
 
36
+ VALID_KEY = "@kzr0x"
 
 
37
 
38
+ @app.get("/")
39
+ def home(key: str = Query(..., description="API Key required")):
40
+ if not is_api_valid():
41
+ return {"status": "error", "message": "API Expired! Valid only for 3 weeks from 27-June-2026."}
42
+ if key != VALID_KEY:
43
+ return {"status": "error", "message": "Invalid API key"}
44
+ return {"status": "success", "message": "API Live! Use /search"}
45
 
46
  @app.get("/search")
47
+ async def search_data(
48
+ key: str = Query(..., description="API Key required"),
49
+ number: str = Query(None, description="Search by Phone Number"),
50
+ aadhar: str = Query(None, description="Search by Aadhar Number"),
51
+ q: str = Query(None, description="Generic search")
 
 
 
52
  ):
53
+ # === EXPIRY CHECK (SAB SE PEHLE) ===
54
+ if not is_api_valid():
55
+ return {"status": "error", "message": "This API has expired. Valid only for 3 weeks (till 18-July-2026)."}
56
+
57
+ if key != VALID_KEY:
58
+ return {"status": "error", "message": "Invalid or missing API key"}
59
+
60
+ if not number and not aadhar and not q:
61
+ raise HTTPException(status_code=400, detail="Provide number, aadhar, or q")
62
+
63
+ search_term = q or number or aadhar
64
+ URL_ICMR = "https://huggingface.co/datasets/kzropx/icmr-parquet/resolve/main/icmr.parquet"
65
+
66
  try:
67
+ query = f"""
68
+ SELECT name, fathersName, phoneNumber, aadharNumber, address, district, pincode, state, town
69
+ FROM read_parquet('{URL_ICMR}')
70
+ WHERE phoneNumber = ? OR aadharNumber = ?
 
71
  LIMIT 1
72
  """
73
+ result = con.execute(query, [search_term, search_term]).fetchall()
74
+
 
 
 
 
 
 
 
 
 
75
  if not result:
76
  return {
77
  "status": "error",
78
+ "message": f"'{search_term}' not found.",
79
+ "developer": {"name": "@kzr0x", "team": "TEAM DARK KNIGHT APIs"}
80
  }
81
+
 
82
  columns = [desc[0] for desc in con.description]
 
 
83
  return {
84
  "status": "success",
85
+ "data": dict(zip(columns, result[0])),
86
+ "developer": {"name": "@kzr0x", "team": "TEAM DARK KNIGHT APIs"}
87
  }
 
88
  except Exception as e:
89
+ return {"status": "error", "message": str(e)}
 
pinger.py CHANGED
@@ -1,26 +1,12 @@
1
- """Keep-alive pinger: pings the Space's /health endpoint every few minutes
2
- so the container doesn't sleep. Runs as a background process inside the Space
3
- (started from Dockerfile CMD)."""
4
- import os
5
  import time
6
-
7
  import requests
8
 
9
- PORT = os.environ.get("APP_PORT", "7860")
10
- URL = os.environ.get("PING_URL", f"http://127.0.0.1:{PORT}/health")
11
- INTERVAL = int(os.environ.get("PING_INTERVAL", "240"))
12
-
13
-
14
- def _ping_loop():
15
- while True:
16
- try:
17
- r = requests.get(URL, timeout=10)
18
- print(f"[pinger] {URL} -> {r.status_code}", flush=True)
19
- except Exception as e:
20
- print(f"[pinger] error: {e}", flush=True)
21
- time.sleep(INTERVAL)
22
-
23
 
24
- if __name__ == "__main__":
25
- print(f"[pinger] starting, target={URL} interval={INTERVAL}s", flush=True)
26
- _ping_loop()
 
 
 
 
 
 
 
 
 
1
  import time
 
2
  import requests
3
 
4
+ URL = "https://kzropx-icmr-data.hf.space"
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
+ while True:
7
+ try:
8
+ requests.get(URL)
9
+ print(f"Pinged {URL} successfully!")
10
+ except Exception as e:
11
+ print(f"Error: {e}")
12
+ time.sleep(300)
requirements.txt CHANGED
@@ -1,4 +1,4 @@
1
  fastapi
2
- duckdb==1.5.3
3
  uvicorn
4
- requests
 
1
  fastapi
2
+ duckdb
3
  uvicorn
4
+ requests