Spaces:
Sleeping
Sleeping
Dink0 commited on
Commit ·
a70c3aa
1
Parent(s): 14ba511
Fix Telegram parsing via jina fallback
Browse files- app.py +49 -37
- requirements.txt +0 -1
app.py
CHANGED
|
@@ -13,31 +13,25 @@ from fastapi import FastAPI
|
|
| 13 |
from fastapi.middleware.cors import CORSMiddleware
|
| 14 |
from pydantic import BaseModel
|
| 15 |
|
| 16 |
-
try:
|
| 17 |
-
from telethon import TelegramClient
|
| 18 |
-
from telethon.sessions import StringSession
|
| 19 |
-
except Exception:
|
| 20 |
-
TelegramClient = None
|
| 21 |
-
StringSession = None
|
| 22 |
-
|
| 23 |
APP_NAME = "pr-tool-backend"
|
| 24 |
|
| 25 |
VK_API_VERSION = os.getenv("VK_API_VERSION", "5.131")
|
| 26 |
VK_ACCESS_TOKEN = os.getenv("VK_ACCESS_TOKEN", "")
|
| 27 |
-
TELEGRAM_API_ID = int(os.getenv("TELEGRAM_API_ID", "0") or "0")
|
| 28 |
-
TELEGRAM_API_HASH = os.getenv("TELEGRAM_API_HASH", "")
|
| 29 |
-
TELEGRAM_STRING_SESSION = os.getenv("TELEGRAM_STRING_SESSION", "")
|
| 30 |
|
| 31 |
# --- Таймауты и параллелизм (всё настраивается через переменные окружения) ---
|
| 32 |
# Таймаут одного HTTP-запроса задаём кортежем (connect, read), чтобы зависший
|
| 33 |
# коннект не съедал всё время.
|
| 34 |
-
# С датацентр-IP (Hugging Face) Telegram
|
| 35 |
-
#
|
|
|
|
| 36 |
# max(..., floor) — защита от слишком маленьких значений в env (например,
|
| 37 |
# случайно выставленного TELEGRAM_OP_TIMEOUT=3.05), которые рвут TG-запросы.
|
| 38 |
-
_TG_CONNECT_TIMEOUT = max(float(os.getenv("TELEGRAM_CONNECT_TIMEOUT", "
|
| 39 |
-
_TG_READ_TIMEOUT = max(float(os.getenv("TELEGRAM_OP_TIMEOUT", "
|
| 40 |
TG_HTTP_TIMEOUT = (_TG_CONNECT_TIMEOUT, _TG_READ_TIMEOUT)
|
|
|
|
|
|
|
|
|
|
| 41 |
_MAX_CONNECT_TIMEOUT = max(float(os.getenv("MAX_CONNECT_TIMEOUT", "10")), 8.0)
|
| 42 |
_MAX_READ_TIMEOUT = max(float(os.getenv("MAX_OP_TIMEOUT", "12")), 8.0)
|
| 43 |
MAX_HTTP_TIMEOUT = (_MAX_CONNECT_TIMEOUT, _MAX_READ_TIMEOUT)
|
|
@@ -50,9 +44,16 @@ VK_MAX_RETRIES = int(os.getenv("VK_MAX_RETRIES", "5"))
|
|
| 50 |
VK_RETRY_DELAY = float(os.getenv("VK_RETRY_DELAY", "0.45"))
|
| 51 |
VK_BATCH_SIZE = int(os.getenv("VK_BATCH_SIZE", "100"))
|
| 52 |
|
| 53 |
-
#
|
| 54 |
-
#
|
| 55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
|
| 57 |
# Общий бюджет времени на весь запрос. По истечении возвращаем то, что успели
|
| 58 |
# обработать, а остальное помечаем как «превышено время» — вместо того, чтобы
|
|
@@ -217,35 +218,46 @@ def canonicalize_max_link(link: str) -> Tuple[Optional[str], Optional[str], Opti
|
|
| 217 |
return canonical, slug, post_id
|
| 218 |
|
| 219 |
|
| 220 |
-
def _telethon_ready() -> bool:
|
| 221 |
-
return bool(
|
| 222 |
-
TelegramClient
|
| 223 |
-
and StringSession
|
| 224 |
-
and TELEGRAM_API_ID
|
| 225 |
-
and TELEGRAM_API_HASH
|
| 226 |
-
and TELEGRAM_STRING_SESSION
|
| 227 |
-
)
|
| 228 |
-
|
| 229 |
-
|
| 230 |
# ---------- Обработчики одной ссылки ----------
|
| 231 |
|
| 232 |
def process_telegram_link(channel_username: str, message_id: str, canonical_link: str) -> Tuple[str, int]:
|
| 233 |
-
|
| 234 |
-
f"https://t.me/{channel_username}/{message_id}?embed=1",
|
| 235 |
-
f"https://t.me/s/{channel_username}/{message_id}",
|
| 236 |
-
]
|
| 237 |
-
fallback_urls = []
|
| 238 |
if ENABLE_JINA_FALLBACK:
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 242 |
|
| 243 |
session = _get_session()
|
| 244 |
page_html = None
|
| 245 |
last_err: Optional[Exception] = None
|
| 246 |
-
for url
|
| 247 |
try:
|
| 248 |
-
resp = session.get(url, timeout=
|
| 249 |
if resp.status_code == 200 and resp.text:
|
| 250 |
page_html = resp.text
|
| 251 |
break
|
|
|
|
| 13 |
from fastapi.middleware.cors import CORSMiddleware
|
| 14 |
from pydantic import BaseModel
|
| 15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
APP_NAME = "pr-tool-backend"
|
| 17 |
|
| 18 |
VK_API_VERSION = os.getenv("VK_API_VERSION", "5.131")
|
| 19 |
VK_ACCESS_TOKEN = os.getenv("VK_ACCESS_TOKEN", "")
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
# --- Таймауты и параллелизм (всё настраивается через переменные окружения) ---
|
| 22 |
# Таймаут одного HTTP-запроса задаём кортежем (connect, read), чтобы зависший
|
| 23 |
# коннект не съедал всё время.
|
| 24 |
+
# С датацентр-IP (Hugging Face) Telegram блокирует/глушит прямые запросы к t.me,
|
| 25 |
+
# поэтому основной путь — прокси r.jina.ai (см. process_telegram_link). Прямой
|
| 26 |
+
# t.me остаётся резервом и потому держится «fail-fast».
|
| 27 |
# max(..., floor) — защита от слишком маленьких значений в env (например,
|
| 28 |
# случайно выставленного TELEGRAM_OP_TIMEOUT=3.05), которые рвут TG-запросы.
|
| 29 |
+
_TG_CONNECT_TIMEOUT = max(float(os.getenv("TELEGRAM_CONNECT_TIMEOUT", "8")), 4.0)
|
| 30 |
+
_TG_READ_TIMEOUT = max(float(os.getenv("TELEGRAM_OP_TIMEOUT", "8")), 5.0)
|
| 31 |
TG_HTTP_TIMEOUT = (_TG_CONNECT_TIMEOUT, _TG_READ_TIMEOUT)
|
| 32 |
+
# Прокси ходит к Telegram со своей стороны — даём ему больше времени.
|
| 33 |
+
_TG_PROXY_TIMEOUT = max(float(os.getenv("TELEGRAM_PROXY_TIMEOUT", "25")), 10.0)
|
| 34 |
+
TG_PROXY_HTTP_TIMEOUT = (10.0, _TG_PROXY_TIMEOUT)
|
| 35 |
_MAX_CONNECT_TIMEOUT = max(float(os.getenv("MAX_CONNECT_TIMEOUT", "10")), 8.0)
|
| 36 |
_MAX_READ_TIMEOUT = max(float(os.getenv("MAX_OP_TIMEOUT", "12")), 8.0)
|
| 37 |
MAX_HTTP_TIMEOUT = (_MAX_CONNECT_TIMEOUT, _MAX_READ_TIMEOUT)
|
|
|
|
| 44 |
VK_RETRY_DELAY = float(os.getenv("VK_RETRY_DELAY", "0.45"))
|
| 45 |
VK_BATCH_SIZE = int(os.getenv("VK_BATCH_SIZE", "100"))
|
| 46 |
|
| 47 |
+
# Прокси r.jina.ai — основной путь для Telegram на HF (прямой t.me заблокирован).
|
| 48 |
+
# Включён по умолчанию; можно отключить через ENABLE_JINA_FALLBACK=0.
|
| 49 |
+
# X-Return-Format: html заставляет jina вернуть СЫРОЙ HTML виджета t.me
|
| 50 |
+
# (с tgme_widget_message_views и owner_name), который и парсит наш код.
|
| 51 |
+
ENABLE_JINA_FALLBACK = os.getenv("ENABLE_JINA_FALLBACK", "1") != "0"
|
| 52 |
+
_JINA_HEADERS = {"X-Return-Format": "html"}
|
| 53 |
+
_JINA_API_KEY = os.getenv("JINA_API_KEY", "").strip()
|
| 54 |
+
if _JINA_API_KEY:
|
| 55 |
+
# Ключ снимает строгие лимиты бесплатного тарифа r.jina.ai.
|
| 56 |
+
_JINA_HEADERS["Authorization"] = f"Bearer {_JINA_API_KEY}"
|
| 57 |
|
| 58 |
# Общий бюджет времени на весь запрос. По истечении возвращаем то, что успели
|
| 59 |
# обработать, а остальное помечаем как «превышено время» — вместо того, чтобы
|
|
|
|
| 218 |
return canonical, slug, post_id
|
| 219 |
|
| 220 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
# ---------- Обработчики одной ссылки ----------
|
| 222 |
|
| 223 |
def process_telegram_link(channel_username: str, message_id: str, canonical_link: str) -> Tuple[str, int]:
|
| 224 |
+
urls = []
|
|
|
|
|
|
|
|
|
|
|
|
|
| 225 |
if ENABLE_JINA_FALLBACK:
|
| 226 |
+
urls.extend([
|
| 227 |
+
(
|
| 228 |
+
f"https://r.jina.ai/https://t.me/{channel_username}/{message_id}?embed=1",
|
| 229 |
+
_JINA_HEADERS,
|
| 230 |
+
TG_PROXY_HTTP_TIMEOUT,
|
| 231 |
+
),
|
| 232 |
+
(
|
| 233 |
+
f"https://r.jina.ai/http://t.me/{channel_username}/{message_id}?embed=1",
|
| 234 |
+
_JINA_HEADERS,
|
| 235 |
+
TG_PROXY_HTTP_TIMEOUT,
|
| 236 |
+
),
|
| 237 |
+
(
|
| 238 |
+
f"https://r.jina.ai/http://t.me/s/{channel_username}/{message_id}",
|
| 239 |
+
_JINA_HEADERS,
|
| 240 |
+
TG_PROXY_HTTP_TIMEOUT,
|
| 241 |
+
),
|
| 242 |
+
(
|
| 243 |
+
f"https://r.jina.ai/http://telegram.me/{channel_username}/{message_id}?embed=1",
|
| 244 |
+
_JINA_HEADERS,
|
| 245 |
+
TG_PROXY_HTTP_TIMEOUT,
|
| 246 |
+
),
|
| 247 |
+
])
|
| 248 |
+
|
| 249 |
+
urls.extend([
|
| 250 |
+
(f"https://t.me/{channel_username}/{message_id}?embed=1", None, TG_HTTP_TIMEOUT),
|
| 251 |
+
(f"https://t.me/s/{channel_username}/{message_id}", None, TG_HTTP_TIMEOUT),
|
| 252 |
+
(f"https://telegram.me/{channel_username}/{message_id}?embed=1", None, TG_HTTP_TIMEOUT),
|
| 253 |
+
])
|
| 254 |
|
| 255 |
session = _get_session()
|
| 256 |
page_html = None
|
| 257 |
last_err: Optional[Exception] = None
|
| 258 |
+
for url, headers, timeout in urls:
|
| 259 |
try:
|
| 260 |
+
resp = session.get(url, headers=headers, timeout=timeout)
|
| 261 |
if resp.status_code == 200 and resp.text:
|
| 262 |
page_html = resp.text
|
| 263 |
break
|
requirements.txt
CHANGED
|
@@ -2,4 +2,3 @@ fastapi==0.110.0
|
|
| 2 |
uvicorn[standard]==0.27.1
|
| 3 |
requests==2.31.0
|
| 4 |
pydantic==2.6.1
|
| 5 |
-
telethon==1.36.0
|
|
|
|
| 2 |
uvicorn[standard]==0.27.1
|
| 3 |
requests==2.31.0
|
| 4 |
pydantic==2.6.1
|
|
|