Update main.py
Browse files
main.py
CHANGED
|
@@ -10,11 +10,14 @@ from contextlib import asynccontextmanager
|
|
| 10 |
# --- CONFIG ---
|
| 11 |
API_ID = 21934109
|
| 12 |
API_HASH = 'e7e8c554b9ff88d180983996c33bdf27'
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
# Dynamically bind to Hugging Face's required routing port
|
| 16 |
PORT = int(os.environ.get("PORT", 7860))
|
| 17 |
-
state = {"my_id": None, "
|
| 18 |
|
| 19 |
# Pointing explicitly to the absolute path in the HF container
|
| 20 |
client = TelegramClient('/code/num_lookup_session', API_ID, API_HASH)
|
|
@@ -83,11 +86,12 @@ async def lifespan(app: FastAPI):
|
|
| 83 |
state["my_id"] = me.id
|
| 84 |
|
| 85 |
try:
|
| 86 |
-
print(f"[STARTUP]
|
| 87 |
-
|
| 88 |
-
|
|
|
|
| 89 |
except Exception as e:
|
| 90 |
-
print(f"[CRITICAL STARTUP ERROR] Could not cache
|
| 91 |
|
| 92 |
yield
|
| 93 |
print("[SHUTDOWN] Disconnecting Telegram Client...")
|
|
@@ -97,7 +101,7 @@ app = FastAPI(lifespan=lifespan)
|
|
| 97 |
|
| 98 |
app.add_middleware(
|
| 99 |
CORSMiddleware,
|
| 100 |
-
allow_origins=["https://crm.gudmed.in"],
|
| 101 |
allow_credentials=True,
|
| 102 |
allow_methods=["*"],
|
| 103 |
allow_headers=["*"],
|
|
@@ -105,47 +109,52 @@ app.add_middleware(
|
|
| 105 |
|
| 106 |
@app.get("/")
|
| 107 |
async def root_index():
|
| 108 |
-
return {"status": "healthy", "service": "Telegram Truecaller Polling API"}
|
| 109 |
|
| 110 |
@app.get("/lookup")
|
| 111 |
async def lookup(phone: str):
|
| 112 |
clean_phone = str(phone)[-10:].strip()
|
| 113 |
await ensure_connected()
|
| 114 |
|
| 115 |
-
if not state["my_id"] or not state["
|
| 116 |
raise HTTPException(status_code=503, detail="Telegram client components are uninitialized.")
|
| 117 |
|
| 118 |
try:
|
|
|
|
| 119 |
try:
|
| 120 |
-
last_messages = await client.get_messages(state["
|
| 121 |
start_msg_id = last_messages[0].id if last_messages else 0
|
| 122 |
except Exception:
|
| 123 |
await ensure_connected()
|
| 124 |
-
last_messages = await client.get_messages(state["
|
| 125 |
start_msg_id = last_messages[0].id if last_messages else 0
|
| 126 |
|
| 127 |
command_payload = f"/num {clean_phone}"
|
| 128 |
-
print(f"[API] Dispatching search request: {command_payload}")
|
| 129 |
-
await client.send_message(state["
|
| 130 |
|
| 131 |
-
for
|
| 132 |
-
|
|
|
|
| 133 |
|
| 134 |
try:
|
| 135 |
-
|
|
|
|
| 136 |
except Exception as loop_err:
|
| 137 |
print(f"[API WARNING] Polling read failed on step {i}: {loop_err}. Reconnecting...")
|
| 138 |
await ensure_connected()
|
| 139 |
continue
|
| 140 |
|
| 141 |
for m in messages:
|
|
|
|
| 142 |
if m.id > start_msg_id and m.sender_id != state["my_id"]:
|
| 143 |
if not m.text or any(x in m.text for x in ["Fetching", "Please wait", "Searching", "Typing", "/num"]):
|
| 144 |
continue
|
| 145 |
|
|
|
|
| 146 |
query_match = re.search(r'Query:\s*`?(\d+)`?', m.text, re.IGNORECASE)
|
| 147 |
if query_match and query_match.group(1).endswith(clean_phone):
|
| 148 |
-
print(f"[API] Targeted response packet found on iteration step {i}!")
|
| 149 |
total_records_match = re.search(r'Total Records:\s*(\d+)', m.text, re.IGNORECASE)
|
| 150 |
total_count = int(total_records_match.group(1)) if total_records_match else 0
|
| 151 |
|
|
@@ -157,7 +166,7 @@ async def lookup(phone: str):
|
|
| 157 |
"full_text": m.text
|
| 158 |
}
|
| 159 |
|
| 160 |
-
raise HTTPException(status_code=504, detail="Timeout:
|
| 161 |
|
| 162 |
except HTTPException:
|
| 163 |
raise
|
|
@@ -166,5 +175,4 @@ async def lookup(phone: str):
|
|
| 166 |
raise HTTPException(status_code=500, detail=str(e))
|
| 167 |
|
| 168 |
if __name__ == "__main__":
|
| 169 |
-
# Point directly to "main:app" for proper cloud environment worker execution
|
| 170 |
uvicorn.run("main:app", host="0.0.0.0", port=PORT, loop="asyncio")
|
|
|
|
| 10 |
# --- CONFIG ---
|
| 11 |
API_ID = 21934109
|
| 12 |
API_HASH = 'e7e8c554b9ff88d180983996c33bdf27'
|
| 13 |
+
|
| 14 |
+
# Extracted Peer ID from your web link (-1003794439741)
|
| 15 |
+
# Telethon requires the -100 prefix dropped for entity lookups via ID integer
|
| 16 |
+
TARGET_GROUP_ID = -1003794439741
|
| 17 |
|
| 18 |
# Dynamically bind to Hugging Face's required routing port
|
| 19 |
PORT = int(os.environ.get("PORT", 7860))
|
| 20 |
+
state = {"my_id": None, "group_entity": None}
|
| 21 |
|
| 22 |
# Pointing explicitly to the absolute path in the HF container
|
| 23 |
client = TelegramClient('/code/num_lookup_session', API_ID, API_HASH)
|
|
|
|
| 86 |
state["my_id"] = me.id
|
| 87 |
|
| 88 |
try:
|
| 89 |
+
print(f"[STARTUP] Fetching and caching entity for Group ID: {TARGET_GROUP_ID}")
|
| 90 |
+
# Group must be in the account's dialog history for this to find it instantly
|
| 91 |
+
state["group_entity"] = await client.get_input_entity(TARGET_GROUP_ID)
|
| 92 |
+
print("[STARTUP] Group entity caching completed successfully.")
|
| 93 |
except Exception as e:
|
| 94 |
+
print(f"[CRITICAL STARTUP ERROR] Could not cache Group Entity: {e}")
|
| 95 |
|
| 96 |
yield
|
| 97 |
print("[SHUTDOWN] Disconnecting Telegram Client...")
|
|
|
|
| 101 |
|
| 102 |
app.add_middleware(
|
| 103 |
CORSMiddleware,
|
| 104 |
+
allow_origins=["https://crm.gudmed.in"],
|
| 105 |
allow_credentials=True,
|
| 106 |
allow_methods=["*"],
|
| 107 |
allow_headers=["*"],
|
|
|
|
| 109 |
|
| 110 |
@app.get("/")
|
| 111 |
async def root_index():
|
| 112 |
+
return {"status": "healthy", "service": "Telegram Truecaller Group Polling API"}
|
| 113 |
|
| 114 |
@app.get("/lookup")
|
| 115 |
async def lookup(phone: str):
|
| 116 |
clean_phone = str(phone)[-10:].strip()
|
| 117 |
await ensure_connected()
|
| 118 |
|
| 119 |
+
if not state["my_id"] or not state["group_entity"]:
|
| 120 |
raise HTTPException(status_code=503, detail="Telegram client components are uninitialized.")
|
| 121 |
|
| 122 |
try:
|
| 123 |
+
# Determine the latest message ID in the group before tracking
|
| 124 |
try:
|
| 125 |
+
last_messages = await client.get_messages(state["group_entity"], limit=1)
|
| 126 |
start_msg_id = last_messages[0].id if last_messages else 0
|
| 127 |
except Exception:
|
| 128 |
await ensure_connected()
|
| 129 |
+
last_messages = await client.get_messages(state["group_entity"], limit=1)
|
| 130 |
start_msg_id = last_messages[0].id if last_messages else 0
|
| 131 |
|
| 132 |
command_payload = f"/num {clean_phone}"
|
| 133 |
+
print(f"[API] Dispatching search request to Group: {command_payload}")
|
| 134 |
+
await client.send_message(state["group_entity"], command_payload)
|
| 135 |
|
| 136 |
+
# Poll up to 50 iterations for group environments due to latency differences
|
| 137 |
+
for i in range(50):
|
| 138 |
+
await asyncio.sleep(0.5)
|
| 139 |
|
| 140 |
try:
|
| 141 |
+
# Fetch more messages (limit=5) because group chatter can pass quickly
|
| 142 |
+
messages = await client.get_messages(state["group_entity"], limit=5)
|
| 143 |
except Exception as loop_err:
|
| 144 |
print(f"[API WARNING] Polling read failed on step {i}: {loop_err}. Reconnecting...")
|
| 145 |
await ensure_connected()
|
| 146 |
continue
|
| 147 |
|
| 148 |
for m in messages:
|
| 149 |
+
# Target messages that appeared AFTER our request, and are NOT sent by us
|
| 150 |
if m.id > start_msg_id and m.sender_id != state["my_id"]:
|
| 151 |
if not m.text or any(x in m.text for x in ["Fetching", "Please wait", "Searching", "Typing", "/num"]):
|
| 152 |
continue
|
| 153 |
|
| 154 |
+
# Validate that this payload matches our tracked query sequence
|
| 155 |
query_match = re.search(r'Query:\s*`?(\d+)`?', m.text, re.IGNORECASE)
|
| 156 |
if query_match and query_match.group(1).endswith(clean_phone):
|
| 157 |
+
print(f"[API] Targeted response packet found in group on iteration step {i}!")
|
| 158 |
total_records_match = re.search(r'Total Records:\s*(\d+)', m.text, re.IGNORECASE)
|
| 159 |
total_count = int(total_records_match.group(1)) if total_records_match else 0
|
| 160 |
|
|
|
|
| 166 |
"full_text": m.text
|
| 167 |
}
|
| 168 |
|
| 169 |
+
raise HTTPException(status_code=504, detail="Timeout: Target bot in group didn't answer with query verification.")
|
| 170 |
|
| 171 |
except HTTPException:
|
| 172 |
raise
|
|
|
|
| 175 |
raise HTTPException(status_code=500, detail=str(e))
|
| 176 |
|
| 177 |
if __name__ == "__main__":
|
|
|
|
| 178 |
uvicorn.run("main:app", host="0.0.0.0", port=PORT, loop="asyncio")
|