| import os |
| import re |
| import asyncio |
| import uvicorn |
| from fastapi import FastAPI, HTTPException |
| from fastapi.middleware.cors import CORSMiddleware |
| from telethon import TelegramClient |
| from contextlib import asynccontextmanager |
|
|
| |
| API_ID = 21934109 |
| API_HASH = 'e7e8c554b9ff88d180983996c33bdf27' |
| BOT_USERNAME = '@TruecallerInfoLookupBot' |
|
|
| |
| PORT = int(os.environ.get("PORT", 7860)) |
|
|
| |
| state = {"my_id": None} |
|
|
| |
| |
| client = TelegramClient('/code/lookup_session', API_ID, API_HASH) |
|
|
| def parse_to_json(text: str) -> dict: |
| """Parses the bot text into a structured dictionary.""" |
| e_match = re.search(r'Eyecon.*?Name:\s*`?(.*?)`?(?:\n|$)', text, re.IGNORECASE | re.DOTALL) |
| c_match = re.search(r'CALLAPP.*?Name:\s*`?(.*?)`?(?:\n|$)', text, re.IGNORECASE | re.DOTALL) |
| |
| name1 = e_match.group(1).strip() if e_match else None |
| name2 = c_match.group(1).strip() if c_match else None |
|
|
| data = {} |
| if name1: |
| data["name1"] = name1 |
| if name2: |
| data["name2"] = name2 |
|
|
| if not name1 and not name2: |
| fallback = re.search(r'Name:\s*`?(.*?)`?(?:\n|$)', text, re.IGNORECASE) |
| if fallback: |
| data["name1"] = fallback.group(1).strip() |
|
|
| carrier_match = re.search(r'Carrier:\s*`?(.*?)`?(?:\n|$)', text, re.IGNORECASE) |
| location_match = re.search(r'Location:\s*`?(.*?)`?(?:\n|$)', text, re.IGNORECASE) |
| |
| data["carrier"] = carrier_match.group(1).strip() if carrier_match else "N/A" |
| data["location"] = location_match.group(1).strip() if location_match else "N/A" |
| data["full_text"] = text |
| |
| return data |
|
|
| |
| @asynccontextmanager |
| async def lifespan(app: FastAPI): |
| session_path = "/code/lookup_session.session" |
| print(f"[STARTUP] Looking for session file at: {session_path}") |
| |
| try: |
| print("[STARTUP] Connecting directly to Telegram Network...") |
| await client.connect() |
| except Exception as e: |
| print(f"\n[CRITICAL] Connection failed: {e}\n") |
| raise e |
|
|
| if not await client.is_user_authorized(): |
| print("!!! NOT LOGGED IN. Please verify your 'lookup_session.session' file !!!") |
| else: |
| print("Telethon Connected and Authorized.") |
| me = await client.get_me() |
| state["my_id"] = me.id |
| |
| yield |
| print("[SHUTDOWN] Disconnecting Telegram Client...") |
| await client.disconnect() |
|
|
| app = FastAPI(lifespan=lifespan) |
|
|
| |
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=["https://crm.gudmed.in"], |
| allow_credentials=True, |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| |
| @app.get("/") |
| async def root_index(): |
| return {"status": "healthy", "service": "Telegram Truecaller Polling API"} |
|
|
| |
| @app.get("/lookup") |
| async def lookup(phone: str): |
| |
| clean_phone = str(phone)[-10:].strip() |
| |
| if not state["my_id"]: |
| raise HTTPException(status_code=503, detail="Telegram client not authorized or fully connected.") |
| |
| try: |
| print(f"[API] Sending search payload for target: +91{clean_phone}") |
| |
| await client.send_message(BOT_USERNAME, f'+91{clean_phone}') |
| |
| |
| for i in range(40): |
| await asyncio.sleep(0.5) |
| |
| |
| messages = await client.get_messages(BOT_USERNAME, limit=3) |
| |
| for m in messages: |
| |
| if m.sender_id != state["my_id"]: |
| |
| |
| if not m.text or any(x in m.text for x in ["Searching", "Please wait", "Typing"]): |
| continue |
| |
| |
| if clean_phone in m.text: |
| print(f"[API] Target found on polling loop step {i}! Processing...") |
| return { |
| "status": "success", |
| "phone": clean_phone, |
| "data": parse_to_json(m.text) |
| } |
|
|
| raise HTTPException(status_code=504, detail="Timeout: Bot didn't respond with correct number in time.") |
| |
| except HTTPException: |
| raise |
| except Exception as e: |
| print(f"Lookup Error: {e}") |
| raise HTTPException(status_code=500, detail=str(e)) |
|
|
| if __name__ == "__main__": |
| uvicorn.run("main:app", host="0.0.0.0", port=PORT, loop="asyncio") |