Spaces:
Sleeping
Sleeping
File size: 5,270 Bytes
8490d1b 511ba56 231072a 511ba56 109d656 5d10ce5 109d656 8490d1b 2147d1c e72602f 2147d1c 8490d1b 2147d1c e72602f 2147d1c e72602f e9bfcb7 2147d1c e72602f 2147d1c e9bfcb7 2147d1c e72602f 75fe874 7891d5f 5d10ce5 8619a68 5d10ce5 8619a68 5d10ce5 231072a 8619a68 5d10ce5 231072a 5d10ce5 231072a 5d10ce5 75fe874 7891d5f e72602f 2147d1c e72602f 5d10ce5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | from pydantic import BaseModel
import httpx
import json
from config import TELEGRAM_URL
from ai_service import get_ai_response
from database import db_manager
TELEGRAM_IP = "149.154.167.220"
MAX_TELEGRAM_MESSAGE_LENGTH = 4096
def _sanitize_telegram_text(text: str) -> str:
if text is None:
return ""
normalized = str(text).replace("\r\n", "\n").replace("\r", "\n")
# Remove control/surrogate chars that Telegram can reject.
cleaned = "".join(
ch
for ch in normalized
if (ch in ("\n", "\t") or ord(ch) >= 32) and not (0xD800 <= ord(ch) <= 0xDFFF)
)
return cleaned.strip()
def _split_telegram_message(text: str, max_length: int = MAX_TELEGRAM_MESSAGE_LENGTH):
if len(text) <= max_length:
return [text]
parts = []
remaining = text
while len(remaining) > max_length:
split_at = remaining.rfind("\n", 0, max_length)
if split_at == -1:
split_at = remaining.rfind(" ", 0, max_length)
if split_at == -1:
split_at = max_length
part = remaining[:split_at].strip()
if not part:
part = remaining[:max_length]
split_at = max_length
parts.append(part)
remaining = remaining[split_at:].strip()
if remaining:
parts.append(remaining)
return parts
class ChatInfo(BaseModel):
id: int
username: str = None
first_name: str = None
last_name: str = None
class Message(BaseModel):
chat: ChatInfo
text: str = ""
class WebhookData(BaseModel):
message: Message = None
async def telegram_webhook(data: WebhookData):
try:
if not data.message or not data.message.text:
return {"status": "ok"}
telegram_id = data.message.chat.id
user_text = data.message.text
username = data.message.chat.username
first_name = data.message.chat.first_name
print(f"--- Processing message from {first_name} ---")
if db_manager:
db_manager.create_or_update_user(telegram_id, username, first_name, data.message.chat.last_name)
ai_answer = await get_ai_response(user_text, telegram_id)
if TELEGRAM_URL:
try:
from config import TELEGRAM_TOKEN
async with httpx.AsyncClient(timeout=40.0, verify=False, follow_redirects=True) as client:
prepared_text = _sanitize_telegram_text(
ai_answer or "Sorry, I couldn't generate a response. Please try again."
)
if not prepared_text:
prepared_text = "Sorry, I couldn't generate a response. Please try again."
message_parts = _split_telegram_message(prepared_text, MAX_TELEGRAM_MESSAGE_LENGTH)
for idx, part in enumerate(message_parts, start=1):
payload = {
"chat_id": telegram_id,
"text": part,
}
print(
f"--- Sending Telegram message part {idx}/{len(message_parts)} "
f"(chars={len(part)}) ---"
)
try:
# Use form data for maximal compatibility with Telegram endpoint parsers.
response = await client.post(TELEGRAM_URL, data=payload)
except Exception:
print(f"--- DNS Failed. Forcing Direct IP Routing to {TELEGRAM_IP} ---")
forced_ip_url = f"https://{TELEGRAM_IP}/bot{TELEGRAM_TOKEN}/sendMessage"
json_body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
headers = {
"Host": "api.telegram.org",
"Content-Type": "application/json; charset=utf-8",
"Content-Length": str(len(json_body)),
}
response = await client.post(
forced_ip_url,
content=json_body,
headers=headers,
)
if response.status_code != 200:
print(f"--- Telegram payload rejected (part {idx}) ---")
print(f"--- Payload: {payload} ---")
print(
f"--- Telegram Rejected Request: "
f"{response.status_code} - {response.text} ---"
)
break
else:
print("--- Success: All Telegram message parts delivered ---")
except Exception as send_error:
print(f"--- Emergency: Network Blockage Detected: {str(send_error)} ---")
return {"status": "ok"}
except Exception as e:
print(f"Error in webhook: {str(e)}")
return {"status": "error", "message": str(e)}
|